diff options
author | root <root@ghunt-desktop.(none)> | 2010-08-26 04:21:13 (GMT) |
---|---|---|
committer | root <root@ghunt-desktop.(none)> | 2010-08-26 04:21:13 (GMT) |
commit | e46eba6769a1e12606c79d462bedeeaebae7d856 (patch) | |
tree | 73d3a4bfecc5fda76d2d220918d2ed0a47878ca0 | |
parent | 2d77413f14aa899adb16217362668cf943f2d368 (diff) |
a week of bug fixes after version 7 was put up
-rw-r--r-- | assets/closed_hand.xbm | 28 | ||||
-rw-r--r-- | assets/closed_hand_mask.xbm | 28 | ||||
-rw-r--r-- | dbphoto.py | 24 | ||||
-rw-r--r-- | display.py | 135 | ||||
-rw-r--r-- | help/xophoto.html | 3 | ||||
-rwxr-xr-x | mkdir_Pictures | 3 | ||||
-rw-r--r-- | sinks.py | 20 | ||||
-rw-r--r-- | xophotoactivity.py | 17 |
8 files changed, 216 insertions, 42 deletions
diff --git a/assets/closed_hand.xbm b/assets/closed_hand.xbm new file mode 100644 index 0000000..d333d8b --- /dev/null +++ b/assets/closed_hand.xbm @@ -0,0 +1,28 @@ +#define closed_hand_width 48 +#define closed_hand_height 48 +static char closed_hand_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC3, 0xE1, 0x00, 0x00, + 0x00, 0xC0, 0xE7, 0xF3, 0x71, 0x00, 0x00, 0xC0, 0xE7, 0xF3, 0xF9, 0x00, + 0x00, 0xC0, 0xE7, 0xF3, 0xF9, 0x00, 0x00, 0xC0, 0xE7, 0xF3, 0xF9, 0x00, + 0x00, 0xC0, 0xE7, 0xF3, 0xF9, 0x00, 0x00, 0xC7, 0xE7, 0xF3, 0xF9, 0x00, + 0x80, 0xCF, 0xFF, 0xFF, 0xF9, 0x00, 0x80, 0xCF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xCF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xCF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xCF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, + 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x07, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; diff --git a/assets/closed_hand_mask.xbm b/assets/closed_hand_mask.xbm new file mode 100644 index 0000000..0552a4e --- /dev/null +++ b/assets/closed_hand_mask.xbm @@ -0,0 +1,28 @@ +#define closed_hand_mask_width 48 +#define closed_hand_mask_height 48 +static char closed_hand_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE7, 0xF3, 0x01, 0x00, + 0x00, 0xE0, 0xFF, 0xFF, 0xFB, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x01, + 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x03, + 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, + 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, + 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, + }; @@ -119,6 +119,11 @@ class DbAccess(): cursor.execute('select * from groups where category = ?',('albums',)) return cursor.fetchall() + def get_albums_containing(self,jobject_id): + cursor = self.connection().cursor() + cursor.execute('select * from groups where jobject_id = ?',(jobject_id,)) + return cursor.fetchall() + def get_album_thumbnails(self,album_id,is_journal=False): if is_journal: #is_journal: #want most recent first, need left join because picture may not exist yet #sql = """select groups.*, data_cache.picture.* from groups left join data_cache.picture \ @@ -416,6 +421,25 @@ values (?,?,?,?,?,?,?,?)""",(jobject_id,w,h,x_thumb,y_thumb,thumb_binary,transfo cursor.execute('rollback transaction') _logger.error('error deleting all references for object:%s. Error: ;%s'%(jobject_id,e,)) + def set_config(self,name,value): + cursor = self.connection().cursor() + cursor.execute('select * from config where name = ?',(name,)) + rows = cursor.fetchall() + if len(rows)>0: + cursor.execute("update config set value = ? where id = ?",(album_id,rows[0]['id'])) + else: + cursor.execute("insert into config (name,value) values (?,?)",(name,value,)) + self.con.commit() + + def get_config(self,name): + cursor = self.connection().cursor() + cursor.execute('select * from config where name = ?',(name,)) + rows = cursor.fetchall() + if len(rows)>0: + return rows[0]['value'] + else: + return '' + def table_exists(self,table): try: sql = 'select * from %s'%table @@ -37,6 +37,8 @@ import time from threading import Timer import datetime import gobject +#from struct import unpack +from array import array #application imports from dbphoto import * @@ -421,8 +423,11 @@ class OneAlbum(): pygame.display.flip() def repaint_whole_screen(self): - self._parent.paint_albums() - self.repaint() + if self.large_displayed: + pass + else: + self._parent.paint_albums() + self.repaint() def release_cycles(self): while gtk.events_pending(): @@ -471,6 +476,8 @@ class OneAlbum(): """album name is title stored in groups.jobject_id where category='albums' This should be called after display thumbnails because the thumbnail routine counts the number of images which this routine displays to the user + comment: this requirement led to Bug 2234 (incorrect count on drop image) -- so + count the thumbnails whenever album (left side) is displayed """ surf = pygame.Surface((album_column_width,album_height)) @@ -482,7 +489,10 @@ class OneAlbum(): else: surf.fill(album_background_color) album_id = rows[index]['subcategory'] - count = rows[index]['seq'] + + #bug 2234 thumbnail count incorrect until click on left column + count = self.db.get_thumbnail_count(rows[index]['subcategory']) + album = rows[index]['jobject_id'] if album_id == trash_id: @@ -1045,44 +1055,87 @@ class DisplayAlbums(): def start_grab(self,x,y): global in_grab - self.start_grab_x = x - self.start_grab_y = y + _logger.debug('start_grab x:%s y:%s in_grab %s'%(x,y,in_grab,)) #change the cursor some way if in_grab: in_grab = False self._activity.window.set_cursor(None) + self.drop_image(self.start_grab_x,self.start_grab_y,x,y) else: in_grab = True + self.start_grab_x = x + self.start_grab_y = y 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) + bitstring = self.xbm_to_data(fn) + if len(bitstring) == 0: return #error state 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() + maskstring = self.xbm_to_data(fn) + if len(maskstring) == 0: return #error state 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)) + self._activity.window.set_cursor(gtk.gdk.Cursor(bitmask,bitpattern,\ + gtk.gdk.Color(255,255,255),gtk.gdk.Color(255,255,255),24,24)) + def xbm_to_data(self,xbm_file): + if not os.path.isfile(xbm_file):return '' + fd = open(xbm_file,'r') + lines = fd.readlines() + byte_array = () + w = None + h = None + index = 0 + byte_array = array('B') + rtn_val = '' + for l in lines: + if len(l.strip()) == 0: continue + if l[0] == '#': + lh = l.find('height') + if lh > -1: + h = int(l[lh+6:]) + lw = l.find('width') + if lw > -1: + w = int(l[lw+5:]) + else: + if not (w and h): return '' + if index == 0: + num_bytes = w * h / 8 + #examine a case where there might be a hex number after bracket + brac = l.find('{') + if brac > -1: + if brac < len(l)-2: #shift it + l = l[brac+1:] + else: + continue + brac = l.find('}') + if brac > -1: continue + hex_list = l.split(', ') + for i in range(len(hex_list)): + chunk = hex_list[i].strip() + if len(chunk) == 0: continue + if chunk[-1:] == ',': + chunk = chunk[:-1] + try: + pass + byte_array.append(int(chunk,16)) + #hex_val = int(chunk,16) + except Exception,e: + _logger.debug('hex parse error: %s Input: %s line:%s'%(e,chunk,l,)) + rtn_val += chunk + ', ' + index += 1 + return byte_array + def drop_image(self, start_x,start_y,drop_x, drop_y): self._activity.window.set_cursor(None) + _logger.debug('drop_image start_x:%s start_y:%s drop_x:%s drop_y:%s'%(start_x,start_y,drop_x,drop_y,)) if drop_x < album_column_width: #we are dropping on album side of screen 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() + _logger.debug('drop_image index:%s jobject_id:%s current_album_id:%s'%(index,jobject_id,current_album_id,)) #if item dragged from trash, put it back in journal_id as well as target stack if current_album_id == trash_id: @@ -1261,8 +1314,11 @@ class Application(): 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() - _logger.debug('pygame_repaint completed') + if album_object.large_displayed: + self.vs.display_large() + else: + album_object.repaint_whole_screen() + _logger.debug('pygame_repaint completed') return False def do_startup(self): @@ -1302,8 +1358,11 @@ class Application(): self.util.remove_alert(alert) #if the picture table is empty, populate it from the journal, and initialize - if ds_count < 10: + #fix for bug 2223 loads images repeatedly into journal + start_images_loaded = self.db.get_config('image_init') + if ds_count < 10 and start_images_loaded == '': self.first_run_setup() + self.db.set_config('image_init','True') self.album_collection = DisplayAlbums(self.db, self._activity) self.album_collection.paint_albums() @@ -1500,6 +1559,7 @@ class Application(): pygame.display.flip() def process_mouse_click(self,event): + global in_grab x,y = event.pos butt = event.button if butt == 4: @@ -1509,18 +1569,23 @@ class Application(): self.album_collection.album_objects[self.album_collection.selected_album_id].scroll_down() else: l,m,r = pygame.mouse.get_pressed() - print('mouse single click') - if x < album_column_width -thick: - #scroll_x,scroll_y = self.album_collection.album_sb.get_scrolled() - rtn_val = self.album_collection.click(x,y) - if not rtn_val: - #create a new album - pass - elif x > album_column_width and x < (screen_w - thick): - if l: - self.album_collection.album_objects[self.album_collection.selected_album_id].click(x,y) - elif r: - self.album_collection.start_grab(x,y) + _logger.debug('mouse single click') + if r: + self.album_collection.start_grab(x,y) + else: + if x < album_column_width -thick: + #scroll_x,scroll_y = self.album_collection.album_sb.get_scrolled() + rtn_val = self.album_collection.click(x,y) + if not rtn_val: + #create a new album + pass + elif x > album_column_width and x < (screen_w - thick): + if l: + if in_grab: #initiated by a right click + self._activity.window.set_cursor(None) + in_grab = False + else: + self.album_collection.album_objects[self.album_collection.selected_album_id].click(x,y) pygame.display.flip() def process_mouse_double_click(self,event): diff --git a/help/xophoto.html b/help/xophoto.html index db08022..7b1edd7 100644 --- a/help/xophoto.html +++ b/help/xophoto.html @@ -53,7 +53,8 @@ Images can be removed from the stack by dragging them to the trash. When items <p>Thereafter, whenever you export a stack of pictures, by default they will be placed in the "/home/olpc/Pictures" 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><a href="http://bugs.sugarlabs.org/newticket?component=XoPhoto> +http://bugs.sugarlabs.org/newticket?component=XoPhoto</a> <p>or send email with "XoPhoto Bug" in the title to "georgejhunt@gmail.com" describing the problem, and the software Build number from "My Settings" -- "About My Computer" (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 "My Settings", left click on "softare update" -- on a recent build you need to use the horizontal scroll bar to make "software Update" visible). </p> <p> </p> diff --git a/mkdir_Pictures b/mkdir_Pictures new file mode 100755 index 0000000..59bcbc5 --- /dev/null +++ b/mkdir_Pictures @@ -0,0 +1,3 @@ +#bash file to create Pictures folder, and set world writeable permissions +mkdir -p -m 777 /home/olpc/Pictures + @@ -52,6 +52,7 @@ class ViewSlides(): gobject.timeout_add(1000, self.__timeout) self.current_time = 1 #set so the first call of timeout will initiate action self.running = False + self.paint = None #display.screen.fill((0,0,0)) #pygame.display.flip() @@ -82,11 +83,9 @@ class ViewSlides(): jobject_id = self.rows[self.index]['jobject_id'] if not jobject_id: return - paint = self.transform_scale_slide(jobject_id) - if paint: - display.screen.blit(paint,(0,0)) - pygame.display.flip() - + self.paint = self.transform_scale_slide(jobject_id) + if self.paint: + self.display_large() self.index += 1 if self.index == len(self.rows): if self.loop: @@ -95,6 +94,12 @@ class ViewSlides(): self.index -= 1 self.album_object.thumb_index = self.index + def display_large(self): + self.album_object.large_displayed = True + display.screen.blit(self.paint,(0,0)) + pygame.display.flip() + + def transform_scale_slide(self,jobject_id): """return surface transformed per database transforms,onto screen sized target""" _logger.debug('entered transform_scale_slide') @@ -176,6 +181,10 @@ class ViewSlides(): return target_surf def run(self): + if len(self.rows) == 0: + self._parent.util.alert(_('Please select a stack that contains images'),_('Cannot show a slideshow with no images')) + self._parent._activity.use_toolbar.set_running(False) + return self.running = True self.paused = False _logger.debug('started the run loop') @@ -222,6 +231,7 @@ class ViewSlides(): def stop(self): self.running = False #'gtk.STOCK_MEDIA_STOP' + self.album_object.large_displayed = False self.album_object.repaint_whole_screen() diff --git a/xophotoactivity.py b/xophotoactivity.py index a2c6558..a6f2a3e 100644 --- a/xophotoactivity.py +++ b/xophotoactivity.py @@ -256,7 +256,22 @@ class XoPhotoActivity(activity.Activity): self.game.album_collection.delete_album(album_id) def activity_toolbar_empty_trash_cb(self): - self.util.confirmation_alert(_('Are you sure you want to proceed?'),\ + rows = self.DbAccess_object.get_album_thumbnails(trash_id) + number_of_references = 0 + for row in rows: + jobject_id = str(row['jobject_id']) + album_rows = self.DbAccess_object.get_albums_containing(jobject_id) + _logger.debug('album count:%s for jobject_id %s'%(len(album_rows),jobject_id,)) + for album_row in album_rows: + if album_row['category'] == journal_id: continue + if album_row['category'] == trash_id: continue + number_of_references += 1 + if number_of_references > 0: + number = str(number_of_references) + detail = _('These images are used in ') + number + _(' other stacks and will be deleted from them also.') + else: + detail = _('Are you sure you want to proceed?') + self.util.confirmation_alert(detail,\ _('Warning! you are about to completely remove these images from your XO.'),\ self.empty_trash_cb) |