Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@ghunt-desktop.(none)>2010-08-17 13:54:59 (GMT)
committer root <root@ghunt-desktop.(none)>2010-08-17 13:54:59 (GMT)
commit2d77413f14aa899adb16217362668cf943f2d368 (patch)
treec693a66d38059f5ea57ce35b09c7738a98819b4a
parentdb59e958e99bfffacbe797a3a7bd068429347771 (diff)
alpha stage, help with screen shots
-rw-r--r--MANIFEST19
-rw-r--r--activity/activity.info2
-rw-r--r--display.py132
-rw-r--r--dist/XoPhoto-7.xobin0 -> 3323407 bytes
-rw-r--r--help/help.py2
-rw-r--r--help/images/delete_composite.pngbin0 -> 131429 bytes
-rw-r--r--help/images/initial_screen.jpgbin0 -> 65576 bytes
-rw-r--r--help/images/slide_start.pngbin0 -> 200758 bytes
-rw-r--r--help/images/the_new_album.pngbin0 -> 85758 bytes
-rw-r--r--help/xophoto.html28
-rw-r--r--sinks.py12
-rw-r--r--xophotoactivity.py63
12 files changed, 178 insertions, 80 deletions
diff --git a/MANIFEST b/MANIFEST
index 453f105..3187472 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -22,15 +22,19 @@ sinks.pyo
data_cache.sqlite
helptemplate.py
assets/closed_hand.xbm
+assets/trash_del.png
assets/open_hand_mask.xbm
assets/open_hand.xbm
assets/trash_empty.png
assets/closed_hand_mask.xbm
+assets/stack_del.png
assets/nostack1.png
assets/190x152shadow.png
assets/stack_background.png
+assets/stack_new.png
assets/nostack.png
assets/trash_full.png
+assets/stack_export.png
startup_images/2606362543_1598e7efc0_o.jpg
startup_images/2611672629_5f0e2c0e63_o.jpg
startup_images/2928908291_c227faca09.jpg
@@ -48,6 +52,7 @@ sugargame/__init__.py
sugargame/canvas.py
sugargame/event.py
sugargame/canvas.pyo
+activity/activity-2.info
activity/activity-1.info
activity/activity.save
activity/XoPhoto.svg
@@ -55,6 +60,7 @@ activity/scommander.svg
activity/activity.info.gh
activity/activity.info
activity/permissions.info
+activity/activity-3.info
ezscroll/ezscroll.pyo
ezscroll/__init__.pyo
ezscroll/inlineScroll.py
@@ -66,3 +72,16 @@ help/__init__.pyo
help/HelpApi.htm
help/__init__.py
help/help.pyo
+help/xoph.css
+help/xophoto.html
+help/CSS/Georgia_800.css
+help/CSS/Georgia.css
+help/CSS/Accessible_Design.css
+help/CSS/_notes/dwsync.xml
+assets/handcursor_mask.xbm
+assets/handcursor.xbm
+help/imagess
+help/images/slide_start.png
+help/images/delete_composite.png
+help/images/initial_screen.jpg
+help/images/the_new_album.png
diff --git a/activity/activity.info b/activity/activity.info
index 6fa3e10..37078a2 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,7 +1,7 @@
[Activity]
name = XoPhoto
bundle_id = org.laptop.XoPhoto
-activity_version = 3
+activity_version = 7
show_launcher = yes
icon = XoPhoto
class = xophotoactivity.XoPhotoActivity
diff --git a/display.py b/display.py
index b40219e..924822d 100644
--- a/display.py
+++ b/display.py
@@ -48,12 +48,14 @@ from sinks import *
#pick up activity globals
from xophotoactivity import *
+import xophotoactivity
#Display Module globals
mouse_timer = time.time()
in_click_delay = False
in_db_wait = False
in_drag = False
+in_grab = False
screen_h = 0
screen_w = 0
screen = None
@@ -72,6 +74,7 @@ album_height = 190
album_size = (180,165)
album_location = (25,25)
album_aperature = (150,125)
+startup_clock = 0
journal_id = '20100521T10:42'
trash_id = '20100521T11:40'
@@ -347,6 +350,7 @@ class OneAlbum():
#thumbnail_surface is the viewport into thumbnail_world, mapped to screen for each album
self.thumbnail_world = None
+ self.thumbnail_redo_world = False
self.thumbnail_surface = pygame.Surface((screen_w-album_column_width,screen_h)).convert()
self.thumbnail_surface.fill(background_color)
self.num_rows = 1
@@ -366,6 +370,9 @@ class OneAlbum():
"""
Put multiple images on pygame screen.
"""
+ if not new_surface and self.thumbnail_redo_world:
+ self.thumbnail_redo_world = False
+ new_surface = True
#make sure we have the most recent list
is_journal = self.album_id == journal_id
self.rows = self.db.get_album_thumbnails(self.album_id,is_journal)
@@ -632,10 +639,10 @@ class OneAlbum():
row = num // self.pict_per_row
min_y = row * self.xy_size
if min_y < y:
- self.sb.scroll(-self.xy_size * self.sb.ratio)
+ self.sb.scroll((min_y - y) * self.sb.ratio)
max_y = (row + 1) * self.xy_size
if max_y > y + screen_h:
- self.sb.scroll(self.xy_size * self.sb.ratio)
+ self.sb.scroll((max_y - y - screen_h) * self.sb.ratio)
self.repaint()
def scroll_up(self,num=3):
@@ -955,7 +962,7 @@ class DisplayAlbums():
#ask the album object to re-create the world
- self.album_objects[self.accumulation_target].thumbnail_world = None
+ self.album_objects[self.accumulation_target].thumbnail_redo_world = True
self.album_objects[self.accumulation_target].set_top_image(self.accumulation_target)
#self.display_thumbnails(self.accumulation_target,new_surface=True)
@@ -1037,28 +1044,35 @@ class DisplayAlbums():
_logger.debug('could not find jobject_id in add_to_aqlbum_at_xy')
def start_grab(self,x,y):
+ global in_grab
self.start_grab_x = x
self.start_grab_y = y
#change the cursor some way
- """
- fn = os.path.join(os.getcwd(),'assets','closed_hand.xbm')
- patfn = fn
- fd = open(fn,'r')
- bitstring = fd.read()
- bitpattern = gtk.gdk.bitmap_create_from_data(None,bitstring,48,48)
-
- fn = os.path.join(os.getcwd(),'assets','closed_hand_mask.xbm')
- maskfn = fn
- fd = open(fn,'r')
- maskstring = fd.read()
- bitmask = gtk.gdk.bitmap_create_from_data(None,maskstring,48,48)
-
- a, b, c, d = pygame.cursors.load_xbm(patfn,maskfn)
- #pygame.mouse.set_cursor(a,b,c,d)
-
- #self._activity.window.set_cursor(gtk.gdk.Cursor(pattern,mask,gtk.gdk.Color(255,255,255),gtk.gdk.Color(0,0,0),24,24))
- """
- self._activity.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.DOTBOX))
+ if in_grab:
+ in_grab = False
+ self._activity.window.set_cursor(None)
+ else:
+ in_grab = True
+ fn = os.path.join(os.getcwd(),'assets','closed_hand.xbm')
+ #fn = os.path.join(os.getcwd(),'assets','handcursor.xbm')
+ fd = open(fn,'r')
+ bitstring = fd.read()
+ #_logger.debug('cursordata:%s'%bitstring)
+ bitpattern = gtk.gdk.bitmap_create_from_data(None,bitstring,48,48)
+
+ fn = os.path.join(os.getcwd(),'assets','closed_hand_mask.xbm')
+ #fn = os.path.join(os.getcwd(),'assets','handcursor_mask.xbm')
+ maskfn = fn
+ fd = open(fn,'r')
+ maskstring = fd.read()
+ bitmask = gtk.gdk.bitmap_create_from_data(None,maskstring,48,48)
+
+ #a, b, c, d = pygame.cursors.load_xbm(patfn,maskfn)
+ #pygame.mouse.set_cursor(a,b,c,d)
+
+
+ self._activity.window.set_cursor(gtk.gdk.Cursor(bitpattern,bitmask,gtk.gdk.Color(255,255,255),gtk.gdk.Color(0,0,0),24,24))
+ #self._activity.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.DOTBOX))
def drop_image(self, start_x,start_y,drop_x, drop_y):
self._activity.window.set_cursor(None)
@@ -1067,10 +1081,32 @@ class DisplayAlbums():
jobject_id = self.album_objects[self.selected_album_id].get_jobject_id_at_xy(start_x,start_y)
index = self.get_album_index_at_xy(drop_x, drop_y)
if not index or not jobject_id: return
+
+ current_album_id = self.get_current_album_identifier()
+ #if item dragged from trash, put it back in journal_id as well as target stack
+ if current_album_id == trash_id:
+ self.db.delete_image(trash_id,jobject_id)
+ self.album_objects[current_album_id].paint(True)
+
+ #unconditionally add the thumbnail back into the list of journal pictures
+ self.db.add_image_to_album(journal_id, jobject_id)
+ self.album_objects[journal_id].thumbnail_redo_world = True
+ if current_album_id != journal_id: #add it to the target also
+ if index > len(self.album_rows)-1:
+ self.create_new_album(self.default_name)
+ self.db.add_image_to_album(self.accumulation_target, jobject_id)
+ self.album_objects[self.accumulation_target].set_top_image(jobject_id)
+ else:
+ self.db.add_image_to_album(self.album_rows[index]['subcategory'], jobject_id)
+ #guarantee full repaint of thumbnails on next repaint
+ self.album_objects[trash_id].thumbnail_redo_world = True
+ self.refresh_album_rows()
+ self.paint_albums()
+ return
+
#if dropped on the trash icon
if self.get_album_id_at_index(index) == trash_id: #a request to delete
- current_album_id = self.get_current_album_identifier()
self.db.delete_image(current_album_id,jobject_id)
self.album_objects[current_album_id].paint(True)
if current_album_id == journal_id:
@@ -1091,7 +1127,7 @@ class DisplayAlbums():
self.refresh_album_rows()
self.paint_albums()
#guarantee that the next time the thumb nails are painted, the new one is included
- self.album_objects[self.accumulation_target].thumbnail_world = None
+ self.album_objects[self.accumulation_target].thumbnail_redo_world = True
#the drop was on thumbnail side of screen, this is a reorder request
else:
@@ -1196,7 +1232,6 @@ class Application():
def __init__(self, activity):
self._activity = activity
#self._activity.window.connect('activate-focus',self.expose_event_cb)
- self.in_grab = False
self.file_tree = None
self.util = Utilities(self._activity)
self.album_collection = None
@@ -1221,22 +1256,15 @@ class Application():
self.pygame_repaint()
def pygame_repaint(self):
- _logger.debug('pugame_repaint')
+ _logger.debug('pygame_repaint')
if not self.album_collection: return
album_id = self.album_collection.selected_album_id
album_object = self.album_collection.album_objects.get(album_id,None)
if not album_object: return
album_object.repaint_whole_screen()
- pygame.display.flip()
- """
- def show_progress(self,button,id):
- self.pa = ProgressAlert()
- self._activity.add_alert(self.pa)
- self.pa.connect('response',self._response_cb)
-
- def _response_cb(self,alert,response):
- self._activity.remove_alert(self.pa)
- """
+ _logger.debug('pygame_repaint completed')
+ return False
+
def do_startup(self):
start = time.clock()
@@ -1248,7 +1276,7 @@ class Application():
c.execute('vacuum')
conn.commit()
- #alert = self.util.alert(_('A quick check of the Journal for new images'),_('PLEASE BE PATIENT'))
+ alert = self.util.alert(_('A quick check of the Journal for new images'),_('PLEASE BE PATIENT'))
try:
#this step took 2.5 seconds to add 195 records to picture from datastore on 1.5XO
#and 1 second when no records were added
@@ -1271,7 +1299,7 @@ class Application():
self.db = self.DbAccess_object
_logger.debug('check for recent images took %f seconds'%(time.clock()-start))
- #self.util.remove_alert(alert)
+ self.util.remove_alert(alert)
#if the picture table is empty, populate it from the journal, and initialize
if ds_count < 10:
@@ -1298,6 +1326,10 @@ class Application():
self.vs.set_album_object(album_object)
return album_object
+ def end_db_delay(self):
+ global in_db_wait
+ in_db_wait = False
+
def run(self):
global screen
global in_click_delay
@@ -1305,11 +1337,24 @@ class Application():
global screen_h
global in_db_wait
global in_drag
+ global startup_clock
+ startup_clock = xophotoactivity.startup_clock
if True:
+ if not self._activity.DbAccess_object: #we need to wait for the read-file to finish
+ Timer(5.0, self.end_db_delay, ()).start()
+ in_db_wait = True
+ while not self._activity.DbAccess_object and in_db_wait:
+ gtk.main_iteration()
+ if not self._activity.DbAccess_object:
+ _logger.error('db object not open after timeout in Appplication.run')
+ dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite')
+ try:
+ self._activity.DbAccess_object = DbAccess(dest)
+ except Exception,e:
+ _logger.debug('database failed to open after timeout. error:%s'%e)
+ exit()
+
self.db = self._activity.DbAccess_object
- if not self.db.is_open():
- _logger.debug('failed to open "xophoto.sqlite" database')
- exit()
self.ds_sql = Datastore_SQLite(self.db)
screen = pygame.display.get_surface()
@@ -1322,6 +1367,7 @@ class Application():
screen.fill((album_background_color))
pygame.display.flip()
+ _logger.debug('about to do_startup. Startup Clock:%f'%(time.clock()-startup_clock))
self.do_startup()
# Flip Display
@@ -1329,6 +1375,7 @@ class Application():
running = True
x = 0 #initialize in case there is no mouse event
+ _logger.debug('About to start running loop. Startup Clock:%f'%(time.clock()-startup_clock,))
while running:
#pygame.display.flip()
# Pump GTK messages.
@@ -1365,6 +1412,8 @@ class Application():
#mouse events
elif event.type == MOUSEBUTTONDOWN:
+ if event.button > 3:
+ _logger.debug('finally got a wheel event')
if event.button < 4 and self.mouse_timer_running(): #this is a double click
self.process_mouse_double_click( event)
in_click_delay = False
@@ -1471,7 +1520,6 @@ class Application():
if l:
self.album_collection.album_objects[self.album_collection.selected_album_id].click(x,y)
elif r:
- self.in_grab = True
self.album_collection.start_grab(x,y)
pygame.display.flip()
diff --git a/dist/XoPhoto-7.xo b/dist/XoPhoto-7.xo
new file mode 100644
index 0000000..4507e32
--- /dev/null
+++ b/dist/XoPhoto-7.xo
Binary files differ
diff --git a/help/help.py b/help/help.py
index 75e1ccd..1d8dfe7 100644
--- a/help/help.py
+++ b/help/help.py
@@ -72,7 +72,7 @@ class Help(Window):
#Mimic the other tabs (hide the fact that this is another window)
self.toolbox = Toolbox()
- self.toolbox.connect('current_toolbar_changed',self.goto_cb)
+ self.toolbox.connect_after('current_toolbar_changed',self.goto_cb)
self.set_toolbox(self.toolbox)
self.toolbox.show()
diff --git a/help/images/delete_composite.png b/help/images/delete_composite.png
new file mode 100644
index 0000000..0856409
--- /dev/null
+++ b/help/images/delete_composite.png
Binary files differ
diff --git a/help/images/initial_screen.jpg b/help/images/initial_screen.jpg
new file mode 100644
index 0000000..b6f792e
--- /dev/null
+++ b/help/images/initial_screen.jpg
Binary files differ
diff --git a/help/images/slide_start.png b/help/images/slide_start.png
new file mode 100644
index 0000000..879c94e
--- /dev/null
+++ b/help/images/slide_start.png
Binary files differ
diff --git a/help/images/the_new_album.png b/help/images/the_new_album.png
new file mode 100644
index 0000000..856c4ad
--- /dev/null
+++ b/help/images/the_new_album.png
Binary files differ
diff --git a/help/xophoto.html b/help/xophoto.html
index c1e3a55..db08022 100644
--- a/help/xophoto.html
+++ b/help/xophoto.html
@@ -8,6 +8,8 @@
<body>
<h1>XoPhoto Features</h1>
+<p><img class="right" src="images/initial_screen.jpg" alt="initial_screen" /></p>
+<p>&nbsp; </p>
<ul>
<li>Select pictures from the Journal and put them into a Stack on the left side of the screen.</li>
<li>Create and name new Stacks, and delete old ones</li>
@@ -22,29 +24,39 @@
<p>Initially there will be only two items visible on the left. The top one is labeled &quot;All Pictures&quot; and shows the number of pictures found in the Journal. The second is labeled &quot;Trash 0&quot;. As you are working with the pictures in &quot;All Pictures&quot;, there may be images which you want to discard. You can drag them to the &quot;Trash&quot; by left clicking on the undesired image, holding the left button down as you move the cursor over the image of the trash, and releasing the left button.</p>
<p>On the XO this usually takes two hands, one to control the left button, and the other to move the cursor. An alternative, and easier method is to click the right button on the undesired image, move the cursor to the trash, and then click the right button again.</p>
<h3>Creating a new Stack of images </h3>
+<p><img class="left" src="images/the_new_album.png" width="400" height="300" alt="creating_album" /></p>
<p>At any time, the user can start a new stack by clicking the icon with the green plus sign. The default name is &quot;New Stack&quot;. It can be renamed by typing the new name in the field labeled &quot;New Album Name&quot;. </p>
<p>In a similar fashion, a stack can be deleted by clicking the &quot;stack&quot; icon with the red X overlayed upon it. For deleting a stack, you must confirm your intention before the stack will be deleted.</p>
<p>As a special case, if there are no Stacks in the left column (only &quot;All Pictures&quot; and the &quot;Trash&quot;), a &quot;New Stack&quot; will be created if the user double clicks on an image in the &quot;All Pictures&quot; set of images. Thereafter, double clicking will add the &quot;double clicked image&quot; to the most recently used stack.</p>
<h3>Manipulating Images on a Stack </h3>
<p>The order of the images in a stack can be changed by the drag and drop method mentioned above. Left click on the item to be moved, and hold it down while dragging the image to the new location.</p>
-<p>Images can be removed from the stack by dragging them to the trash. When stack items are dragged to the trash, they just disappear. They are not added to the contents of the trash. Only the images that are dragged from &quot;All Pictures&quot; are added to the contents of the trash basket. When you have selected the Trash, the contents of the Trash Basked are visible, and the &quot;Empty Trash&quot; icon becomes visible. When &quot;Trash&quot; is emptied, the corresponding pictures in the Journal are removed from the XO and are not recoverable.</p>
+<h3>Deleting Images from the XO</h3>
+<p><img class="right" src="images/delete_composite.png" width="556" height="458" />
+Images can be removed from the stack by dragging them to the trash. When items from stacks you have created are dragged to the trash, they just disappear. They are not added to the contents of the trash. Only the images that are dragged from &quot;All Pictures&quot; are added to the contents of the trash basket. (Notice that in the multiple image to the right, the contents of the Trash are displayed--the trash basket is the same shade of gray as the right side). When you have selected the Trash, the contents of the Trash Basket are visible, and the &quot;Empty Trash&quot; icon becomes visible (the red X over the Trash image). When &quot;Trash&quot; is emptied, all corresponding pictures are removed from the XO and are not recoverable.</p>
<p>Certain editing operations affect all views: adding Title, Description, and rotating the image.</p>
<h3>Adding Images to XoPhoto from sources </h3>
<p>The XO itself is the most convenient means of adding photos to XoPhoto. The camera adds images to the Journal automatically whenever the Record Activity is used to take pictures. It is more convenient to use the XO as a camera, if the &quot;O&quot; button (one of the four grouped together in diamond shape on the right side of the XO screen) is used as the camera trigger.</p>
<p>Another way of using the XO as a source is to take a screenshot of what is currently on the XO display. This is done via the &lt;alt &quot;1&quot;&gt; key conbination.</p>
-<p>Images can be imported by selecting the &quot;Edit&quot; tab on the menu, and then clicking on the top leftmost icon. USB sticks, and SD cards will become visible and can be selected as import sources.</p>
+<p>Images can be imported by selecting the &quot;Edit&quot; tab on the menu, and then clicking on the top leftmost icon. USB sticks, and SD cards will become visible and can be selected as import sources. The dialogue box will permit the user to select a folder from which all the images will be imported into the XO Journal. Then the next time the XoPhoto program is started up, the new photos in the Journal will be noticed, and the thumbnails will be generated. </p>
<h3>Exporting images </h3>
-<p>A stack of images can be exported to a folder from the Journal by choosing the &quot;Output&quot; tab of the top menu. The current version of XoPhoto exports the image as it was reveived from the source--without rotation, or other transformations. This may change in later versions, as soon as quality and preservation of embedded information issues can be resolved. The exported images will be output in the order of the stack, and with filenames modified to the title given to the image on the &quot;Edit&quot; menu tab. The filenames are prepended with a sequence number so that other slideshow programs will show in the correct order. </p>
-<h3>Slideshow </h3>
+<p>A stack of images can be exported to a folder from the Journal by choosing the &quot;Output&quot; tab of the top menu. The current version of XoPhoto exports the image as it was received from the source--without rotation, or other transformations. This may change in later versions, as soon as quality and preservation of embedded information issues can be resolved. The exported images will be output in the order of the stack, and with filenames modified to the title given to the image on the &quot;Edit&quot; menu tab. The filenames begin with a sequence number so that other slideshow programs will show them in the correct order. </p>
+<p>The location of the folder can be selected using the dialog box which pops up initally. A folder will be generated with the name you entered when you named the photo stack. If a folder with that name already exists, a &quot;-1&quot; or &quot;-2&quot;, etc, will be added to the folder name. </p>
+<h3>Slideshow </h3><img class="right" src="images/slide_start.png" alt="start_slideshow" />
<p>At any time during the viewing of the thumbnails, if the user desires to view a larger view of the image, the &quot;Output&quot; tab &quot;next slide&quot; icon can be selected. This will show the currently selected image at the largest size possible. &quot;Next slide&quot; and &quot;Previous slide&quot; will continue to display large images. The square &quot;Stop&quot; icon will return the user to the thumbnail screen. </p>
-<h3>Preparing the Home/Pictures Directory </h3>
+<h3>Preparing the /home/olpc/Pictures Directory </h3>
<p>There is a procedure required to prepare the /home/olpc/Pictures directory to receive pictures from XoPhoto. This procedure will set the permissions on the &quot;Pictures&quot; directory so that XoPhoto can write. The procedure is a 4 step process:</p>
<ol>
<li>Open the Terminal Activity</li>
<li>Type the characters &quot;cd&quot; and hit the enter key. </li>
- <li>Type the characters &quot;su&quot; and hit the enter key.</li>
- <li>Type the characters &quot;chmod 666 Pictures&quot; and hit the enter key (observe capitalizaion)</li>
+ <li>Type the characters &quot;./A&quot; and hit the &lt;tab&gt; key. The auto-completion will complete the &quot;./Activities/&quot; pathname for you. Then type &quot;X&quot;, &lt;tab&gt;. The path will become &quot;./Activities/XoPhoto.activity/&quot;. Then type 'm',&lt;tab&gt;. The auto-completed path will be &quot;./Activities/XoPhoto.activity/mkdir_Pictures&quot;. Then hit enter, and a short program will be executed which will properly set up your &quot;Pictures&quot; folder. </li>
</ol>
-<p>Done!! (you can tyoe &quot;exit&quot; &lt;enter&gt; &quot;exit&quot; &lt;enter&gt; to end the Terminal session </p>
+<p>Thereafter, whenever you export a stack of pictures, by default they will be placed in the &quot;/home/olpc/Pictures&quot; folder, and they will be available from to the Browse Activity for upload .</p>
+<h3>How to Help Improve XoPhoto . . .Report Bugs </h3>
+<p>You can help make XoPhoto better by reporting the Bugs, and suggestions you have for improvement. Fill out a Bug Report at </p>
+<p>https://bugs.sugarlabs.org/newticket?component=XoPhoto</p>
+<p>or send email with &quot;XoPhoto Bug&quot; in the title to &quot;georgejhunt@gmail.com&quot; describing the problem, and the software Build number from &quot;My Settings&quot; -- &quot;About My Computer&quot; (described in next paragraph). </p>
+<p> The author of XoPhoto will make every effort to provide quick turnaround on fixes, and ensure that the software update activity function provides a convenient means of obtaining the improved activity (From the circle home screen, right click on the XO figure in the center, left click on &quot;My Settings&quot;, left click on &quot;softare update&quot; -- on a recent build you need to use the horizontal scroll bar to make &quot;software Update&quot; visible). </p>
+<p>&nbsp;</p>
+<p>&nbsp;</p>
</body>
</html>
diff --git a/sinks.py b/sinks.py
index 60a4da3..6b8a389 100644
--- a/sinks.py
+++ b/sinks.py
@@ -270,13 +270,15 @@ class ExportAlbum():
ds_object = datastore.get(jobject_id)
if not ds_object:
_logger.debug('failed to fetch ds object %s'%jobject_id)
- return
+ #if the picture was deleted from the datastore, we'll just ignore the error
+ continue
fn = ds_object.get_file_path()
mime_type = self.db.get_mime_type(jobject_id)
lookup = {'image/png':'.png','image/jpg':'.jpg','image/jpeg':'.jpg','image/gif':'.gif','image/tif':'.tif'}
#base = os.path.basename(fn).split('.')
base = self._parent.DbAccess_object.get_title_in_picture(jobject_id)
title = self._parent.DbAccess_object.get_title_in_picture(jobject_id)
+ description = self._parent.DbAccess_object.get_comment_in_picture(jobject_id)
#don't override a suffix that exists
#if len(base) == 1:
if base:
@@ -285,7 +287,7 @@ class ExportAlbum():
else:
base = os.path.basename(fn)
base = base + lookup.get(mime_type,'')
- base = '%s'%index +'_' + base
+ base = '%03d'%index +'_' + base
_logger.debug('exporting %s to %s'%(fn,os.path.join(self.path,base),))
shutil.copy(fn,os.path.join(self.path,base))
ds_object.destroy()
@@ -294,8 +296,10 @@ class ExportAlbum():
ds_object = datastore.get(jobject_id)
md = ds_object.get_metadata()
if md:
- md['title'] = title
- md['description'] = self._parent.DbAccess_object.get_comment_in_picture(jobject_id)
+ if title:
+ md['title'] = title
+ if description:
+ md['description'] = description
tag = md.get('tags','')
if len(tag) == 0:
md['tags'] = self.album
diff --git a/xophotoactivity.py b/xophotoactivity.py
index bf44abe..a2c6558 100644
--- a/xophotoactivity.py
+++ b/xophotoactivity.py
@@ -43,6 +43,7 @@ from sugar import profile
import gobject
import sugargame.canvas
import os
+import time
import shutil
from threading import Timer
from subprocess import Popen, PIPE
@@ -63,6 +64,7 @@ HELP_TAB = 3
#Application Globals
album_column_width = 200
+startup_clock = time.clock()
#db can be resumed, new instance, or recovering from db error
import logging
@@ -101,10 +103,14 @@ class XoPhotoActivity(activity.Activity):
self.make_jobject = False
else:
self.make_jobject = True
- self.read_file(None)
- _logger.debug('At activity startup, handle.object_id is None. Making a new datastore entry')
activity.Activity.__init__(self, handle, create_jobject = self.make_jobject)
+
+ if self.make_jobject:
+ self.read_file(None)
+ self.save()
+ _logger.debug('At activity startup, handle.object_id is None. Making a new datastore entry')
+
#does activity init execute the read? check if dbobject is reliably open
if self.DbAccess_object:
_logger.debug('database object is_open:%s'%self.DbAccess_object.is_open())
@@ -112,33 +118,36 @@ class XoPhotoActivity(activity.Activity):
_logger.debug('after activity init, read has not been called')
self.make_jobject = False
- #following are essential for interface to Help
- self.help_x11 = None
- self.handle = handle
- self.help = Help(self)
-
+ """
self.toolbox = activity.ActivityToolbox(self)
self.toolbox.connect_after('current_toolbar_changed',self._toolbar_changed_cb)
self.toolbox.show()
-
- toolbar = gtk.Toolbar()
- self.toolbox.add_toolbar(_('Help'), toolbar)
- toolbar.show()
-
+ """
# Build the activity toolbar.
self.build_toolbar()
+
+ #following are essential for interface to Help
+ self.help_x11 = None
+ self.handle = handle
+ self.help = Help(self)
+
+ #repaint the screen after a frame event
+ self.toolbox.connect_after('expose-event',self.pygame_repaint_cb)
# Build the Pygame canvas.
+ _logger.debug('Initializing Pygame Canvas. Startup Clock:%f'%(time.clock()-startup_clock,))
self._pygamecanvas = sugargame.canvas.PygameCanvas(self)
- self.toolbox.connect('add',self.pygame_repaint_cb)
# Note that set_canvas implicitly calls read_file when resuming from the Journal.
+ _logger.debug('Setting Activity Canvas. Startup Clock:%f'%(time.clock()-startup_clock,))
self.set_canvas(self._pygamecanvas)
# Create the game instance.
+ _logger.debug('Initializing Game. Startup Clock:%f'%(time.clock()-startup_clock,))
self.game = display.Application(self)
# Start the game running.
+ _logger.debug('Running the Game. Startup Clock:%f'%(time.clock()-startup_clock,))
self._pygamecanvas.run_pygame(self.game.run)
def build_toolbar(self):
@@ -201,7 +210,8 @@ class XoPhotoActivity(activity.Activity):
self.set_toolbox(self.toolbox)
def pygame_repaint_cb(self,widget,event):
- self.game.pygame_repaint()
+ _logger.debug('pygame_repaint_cb')
+ gobject.idle_add(self.game.pygame_repaint)
################ Help routines
def _toolbar_changed_cb(self,widget,tab_no):
@@ -210,7 +220,9 @@ class XoPhotoActivity(activity.Activity):
def set_toolbar(self,tab):
self.toolbox.set_current_toolbar(tab)
-
+ #gobject.idle_add(self.game.pygame_repaint)
+ self.game.pygame_repaint()
+
def help_selected(self):
"""
if help is not created in a gtk.mainwindow then create it
@@ -283,7 +295,8 @@ class XoPhotoActivity(activity.Activity):
source = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite')
ds = datastore.create()
- default_title = _('Saved Stacks')
+ default_title = _('No Stacks')
+ #ds.metadata['title'] = default_title
ds.metadata['title'] = dict.get('title',default_title)
ds.metadata['activity_id'] = dict.get('activity_id')
ds.metadata['activity'] = 'org.laptop.XoPhoto'
@@ -299,10 +312,11 @@ class XoPhotoActivity(activity.Activity):
#sanity check forces check of integrity of thumbnails and picture data, causes
# reload of template if sanity check fails
self.db_sanity_check = False
- #make_object forces copying of the template to data directory
- self.make_object = True
- self.read_file(None)
- self.make_object = False
+ self.read_file(None,initialize=True)
+ self.metadata['title'] = default_title
+ self.activity_toolbar.title.set_text(default_title)
+ #save the newly initialized state
+ self.save()
# Start the game running again.
self.game.do_startup()
@@ -407,7 +421,7 @@ class XoPhotoActivity(activity.Activity):
def read_file(self, file_path, initialize=False):
- _logger.debug('started read_file %s. make_file flag %s'%(file_path,self.make_jobject))
+ _logger.debug('started read_file: %s. make_file flag %s. initialize:%s'%(file_path,self.make_jobject,initialize))
if self.make_jobject or initialize: #make jobject is flag signifying that we are not resuming activity
_logger.debug(' copied template rather than resuming')
if self.DbAccess_object:
@@ -494,7 +508,7 @@ class XoPhotoActivity(activity.Activity):
_logger.debug('data_cache template failed to copy error:%s'%e)
exit()
- _logger.debug('completed read_file. DbAccess_jobject is created')
+ _logger.debug('completed read_file. DbAccess_jobject is created. Since startup:%f'%(time.clock()-startup_clock,))
def write_file(self, file_path):
@@ -533,7 +547,8 @@ class XoPhotoActivity(activity.Activity):
dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite')
try:
self.DbAccess_object = DbAccess(dest)
- self.game.db = self.DbAccess_object
+ if self.game:
+ self.game.db = self.DbAccess_object
except Exception,e:
_logger.debug('database failed to re-open in write file. error:%s'%e)
exit()
@@ -794,7 +809,7 @@ class UseToolbar(gtk.Toolbar):
tool_item.add(self.dwell_entry)
self.dwell_entry.show()
self.insert(tool_item, -1)
- tool_item.show()
+ tool_item.hide()
separator = gtk.SeparatorToolItem()
separator.props.draw = True