diff options
author | root <root@ghunt-desktop.(none)> | 2010-06-12 10:12:16 (GMT) |
---|---|---|
committer | root <root@ghunt-desktop.(none)> | 2010-06-12 10:12:16 (GMT) |
commit | 2415239957382b99e8fde4aa6b0f1d5684f962bb (patch) | |
tree | 8435f1d906e7007b9652f795913877f2be04ffc4 | |
parent | c66d824660bdd9709bde659daf97c0a4017acfcc (diff) |
improvements to add album, partial thumbnail scroll, snapshot for reflash
-rw-r--r-- | activity/permissions.info | 2 | ||||
-rw-r--r-- | data_cache.sqlite | bin | 0 -> 1231872 bytes | |||
-rw-r--r-- | data_cache.sqlite.template | bin | 0 -> 2048 bytes | |||
-rw-r--r-- | dbphoto.py | 80 | ||||
-rw-r--r-- | display.py | 601 | ||||
-rw-r--r-- | photo_toolbar.py | 15 | ||||
-rw-r--r-- | sources.py | 28 | ||||
-rw-r--r-- | sugargame/canvas.py | 19 | ||||
-rw-r--r-- | xophoto.sqlite.template | bin | 12288 -> 12288 bytes | |||
-rw-r--r-- | xophotoactivity.py | 91 |
10 files changed, 506 insertions, 330 deletions
diff --git a/activity/permissions.info b/activity/permissions.info new file mode 100644 index 0000000..431deab --- /dev/null +++ b/activity/permissions.info @@ -0,0 +1,2 @@ +constant-uid + diff --git a/data_cache.sqlite b/data_cache.sqlite Binary files differnew file mode 100644 index 0000000..57b8e38 --- /dev/null +++ b/data_cache.sqlite diff --git a/data_cache.sqlite.template b/data_cache.sqlite.template Binary files differnew file mode 100644 index 0000000..b76b868 --- /dev/null +++ b/data_cache.sqlite.template @@ -29,6 +29,7 @@ import hashlib #pick up activity globals from xophotoactivity import * +import display #define globals related to sqlite sqlite_file_path = None @@ -56,15 +57,34 @@ class DbAccess(): _logger.debug('trying to open database cwd:%s filename %s'%(os.getcwd(),dbfilename,)) dbfilename = os.path.join(os.getcwd(),dbfilename) self.con = sqlite3.connect(dbfilename) + self.dbfilename = dbfilename self.con.row_factory = sqlite3.Row self.con.text_factory = str #rows generated thusly will have columns that are addressable as dict of fieldnames self.cur = self.con.cursor() + path = os.path.dirname(dbfilename) + data_db = os.path.join(path,'data_cache.sqlite') + sql = "attach '%s' as data_cache"%data_db + _logger.debug('attaching using sql %s'%sql) + self.cur.execute(sql) except IOError,e: _logger.debug('open database failed. exception :%s '%(e,)) return None return self.cur + def connection(self): + #test to see if the database is open + if self.con: + try: + cursor = self.con.cursor() + cursor.execute('select * from config') + not_open = False + except: + not_open = True + if not self.con or not_open: + self.opendb(self.dbfilename) + return self.con + def is_open(self): if self.con: return True return False @@ -91,13 +111,17 @@ class DbAccess(): return rows[0]['mime_type'] return None - def get_album_list(self): - sql = 'select max duplicate from picture group by album' - album_list,cur = self.dbdo(sql) - if len(album_list) == 0: - _logger.debug('failed to retrieve albums') - return None - return album_list + def get_albums(self): + cursor = self.connection().cursor() + cursor.execute('select * from groups where category = ?',('albums',)) + return cursor.fetchall() + + def get_album_thumbnails(self,album_id): + sql = """select pict.*, grp.* from picture as pict, groups as grp \ + where grp.category = ? and grp.jobject_id = pict.jobject_id order by create_date desc""" + cursor = self.connection().cursor() + cursor.execute(sql,(str(album_id),)) + return cursor.fetchall() def create_picture_record(self,object_id, fn): """create a record in picture pointing to unique pictures in the journal. @@ -127,14 +151,14 @@ class DbAccess(): (in_ds, mount_point, orig_size, create_date,jobject_id, md5_sum, duplicate) \ values (%s,'%s',%s,'%s','%s','%s',%s)""" % \ (1, fn, info.st_size, info.st_ctime, object_id, md5_hash,len(rows_md5),) - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute(sql) self.con.commit() return 1 elif len(rows) == 1: sql = """update picture set in_ds = ?, mount_point = ?, orig_size = ?, \ create_date = ?, md5_sum = ?, duplicate = ?""" - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute(sql,(1, fn, info.st_size, info.st_ctime, md5_hash,len(rows_md5))) self.con.commit() return 0 @@ -145,15 +169,15 @@ class DbAccess(): #_logger.debug('rowcount %s object_id %s'%(len(rows),object_id)) #the object_id is supposed to be unique, so add only new object_id's if len(rows) == 0: - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute('insert into picture (jobject_id) values (?)',(str(jobject_id),)) self.con.commit() def clear_in_ds(self): - self.con.execute('update picture set in_ds = 0') + self.connection().execute('update picture set in_ds = 0') def delete_not_in_ds(self): - self.con.execute('delete from picture where in_ds = 0') + self.connection().execute('delete from picture where in_ds = 0') def check_in_ds(self,fullpath,size): sql = "select * from picture where mount_point = '%s' and orig_size = %s"%(fullpath,size,) @@ -163,7 +187,7 @@ class DbAccess(): return False def get_last_album(self): - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute("select * from config where name = 'last_album'") rows = cursor.fetchmany() _logger.debug('found %s last albums'%len(rows)) @@ -176,7 +200,7 @@ class DbAccess(): return None,0 def set_last_album(self,album_id): - cursor = self.con.cursor() + cursor = self.connection().cursor() value,id = self.get_last_album() if id > 0: cursor.execute("update config set value = ? where id = ?",(album_id,id)) @@ -185,7 +209,7 @@ class DbAccess(): self.con.commit() def set_album_count(self,album_id,count): - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute("select * from groups where category = 'albums' and subcategory = ?",(str(album_id),)) rows = cursor.fetchmany() if len(rows) == 1: @@ -196,7 +220,7 @@ class DbAccess(): _logger.debug('set album count error:%s'%e) def get_album_count(self,album_id): - cursor = self.con.cursor() + cursor = self.connection().cursor() try: cursor.execute("select * from groups where category = 'albums' and subcategory = ?",(str(album_id,))) rows = cursor.fetchmany() @@ -207,13 +231,14 @@ class DbAccess(): return 0 def create_update_album(self,album_id,name): - cursor = self.con.cursor() + cursor = self.connection().cursor() cursor.execute('select * from groups where category = ? and subcategory = ?',\ ('albums',str(album_id,))) rows = cursor.fetchmany() + _logger.debug('create-update found %s records. album:%s. id:%s'%(len(rows),album_id,name,)) if len(rows)>0 : #pick up the name id = rows[0]['id'] - cursor.execute("update groups set category = ?, subcategory = ?, jobject_id = ? where id = ?",\ + cursor.execute("update groups set subcategory = ?, jobject_id = ? where id = ?",\ (str(album_id),name,id)) else: cursor.execute("insert into groups (category,subcategory,jobject_id,seq) values (?,?,?,?)",\ @@ -221,20 +246,27 @@ class DbAccess(): self.con.commit() def add_image_to_album(self, album_id, jobject_id): - cursor = self.con.cursor() + cursor = self.connection().cursor() + cursor.execute('select max(seq) as max_seq from groups where category = ? group by category',(album_id,)) + rows = cursor.fetchall() + if len(rows)>0: + old_seq = rows[0]['max_seq'] + else: + old_seq = 0 + _logger.debug('failed to get max of seq for album %s'%album_id) #we will try to add the same picture only once cursor.execute("select * from groups where category = ? and jobject_id = ?",\ (str(album_id), str(jobject_id,))) rows = cursor.fetchmany() if len(rows)>0: return None cursor.execute("insert into groups (category,subcategory,jobject_id,seq) values (?,?,?,?)",\ - (str(album_id),'',str(jobject_id),0)) + (str(album_id),'',str(jobject_id),old_seq + 20)) self.con.commit() def table_exists(self,table): try: sql = 'select * from %s'%table - self.con.execute(sql) + self.connection().execute(sql) return True except: return False @@ -259,7 +291,7 @@ class DbAccess(): def fieldlist(self,table): list=[] #accumulator for model - cur = self.con.cursor() + cur = self.connection().cursor() cur.execute('select * from %s'%table) if cur: for field in cur.description: @@ -282,14 +314,14 @@ class DbAccess(): def dbdo(self,sql): """ execute a sql statement or definition, return rows and cursor """ try: - cur = self.con.cursor() + cur = self.connection().cursor() cur.execute(sql) return cur.fetchall(), cur #self.con.commit() except sqlite.Error, e: _logger.debug( 'An sqlite error:%s; sql:%s'%(e,sql,)) self.error = str(e) - raise PhotoException(self.error) + raise display.PhotoException(self.error) def dbtry(self,sql): """ execute a sql statement return true if no error""" @@ -57,21 +57,31 @@ from ezscroll.ezscroll import ScrollBar from xophotoactivity import * #Display Module globals -background_color = (210,210,210) -album_background_color = (170,170,170) -album_selected_color = (210,210,210) -selected_color = (0,230,0) mouse_timer = time.time() in_click_delay = False in_db_wait = False in_drag = False screen_h = 0 screen_w = 0 + #thickness of scroll bar -thick = 20 +thick = 15 sb_padding = 6 -album_display_start = 0 +background_color = (210,210,210) +album_background_color = (170,170,170) +album_selected_color = (210,210,210) +selected_color = (0,230,0) +text_color = (0,0,200) +album_font_size = 30 album_column_width = 200 +album_height = 190 +album_size = (180,165) +album_location = (25,25) +album_aperature = (150,125) + +journal_id = '20100521T10:42' +trash_id = '20100521T11:40' + import logging _logger = logging.getLogger('xophoto.display') @@ -88,7 +98,7 @@ class PhotoException(Exception): def __str__(): return repr(self.value) -class DisplayOne(): +class OneThumbnail(): def __init__(self,rows,db,target,index=0,save_to_db=True): self.rows = rows self.db = db @@ -103,8 +113,9 @@ class DisplayOne(): self.surf = None self.background = (200,200,200) self.scaled = None + self.from_database = False - def paint(self): + def paint_thumbnail(self): """ Put an image on pygame screen. Inputs: 1. cursor pointing to picture records of xophoto.sqlite @@ -112,7 +123,7 @@ class DisplayOne(): """ if not self.scaled: i = self.db.row_index('jobject_id','picture') - id = self.rows[self.row_index][i] + id = self.rows[self.row_index]['jobject_id'] self.surface = pygame.Surface((self.size_x,self.size_y,)) self.surface.fill(background_color) self.scaled = self.scale_image(id,self.size_x,self.size_y) @@ -132,8 +143,9 @@ class DisplayOne(): First check to see if this thumbnail is already in the database, if so, return it If not, generate the thumbnail, write it to the database, and return it """ + #_logger.debug('scale_image id:%s.x:%s. y:%s'%(id,x_size,y_size,)) max_dim = max(x_size,y_size) - 2*self.border - sql = 'select * from transforms where jobject_id = "%s"'%id + sql = 'select * from data_cache.transforms where jobject_id = "%s"'%id rows, cur = self.db.dbdo(sql) for row in rows: w = row['scaled_x'] @@ -147,6 +159,7 @@ class DisplayOne(): blob =row['thumb'] surf = pygame.image.frombuffer(blob,(w,h),'RGB') #_logger.debug('retrieved thumbnail from database') + self.from_database = True return surf try: ds_obj = datastore.get(id) @@ -185,12 +198,13 @@ class DisplayOne(): cursor = conn.cursor() thumb_binary = sqlite3.Binary(thumbstr) try: - cursor.execute("insert into transforms (jobject_id,original_x,original_y,scaled_x,scaled_y,thumb) values (?,?,?,?,?,?)",\ + cursor.execute("insert into data_cache.transforms (jobject_id,original_x,original_y,scaled_x,scaled_y,thumb) values (?,?,?,?,?,?)",\ (id,w,h,self.x_thumb,self.y_thumb,thumb_binary,)) except sqlite3.Error,e: _logger.debug('write thumbnail error %s'%e) return None self.db.commit() + self.from_database = False return ret def position(self,x,y): @@ -217,131 +231,222 @@ class DisplayOne(): return self -class DisplayMany(): +class OneAlbum(): """ Receives an open database object refering to database:'xophoto.sqlite' which is stored in the journal + Displays one album and the associated thumbnails """ - def __init__(self,dbaccess,index=0): - global background_color + def __init__(self,dbaccess,album_id): self.db = dbaccess + self.album_id = album_id self.pict_dict = {} self.large_displayed = False - self.screen_width = screen_w - album_column_width + self.screen_width = screen_w - album_column_width - thick self.screen_height = screen_h - self.picture_surface = pygame.Surface((self.screen_width,self.screen_height)) - self.picture_surface.fill(background_color) self.screen_origin_x = 000 self.screen_origin_y = 000 self.pict_per_row = 5 self.num_rows = 4 - self.display_start_index = index self.origin_row = 0 + self.display_end_index = 0 + self.jobject_id = None + self.thumbnail_world = None + self.thumbnail_surface = pygame.Surface((screen_w-album_column_width-thick,screen_h)).convert() + self.thumbnail_surface.fill(background_color) + + #variable for remembering the state of the thumbnail display + self.display_start_index = 0 + self.thumb_index = 0 self.last_selected = None - def paint(self,rows,index=0): + #figure out what size to paint, assuming square aspect ratio + screen_max = max(self.screen_height,self.screen_width) + self.xy_size = screen_max // self.pict_per_row + + + def paint(self): """ Put multiple images on pygame screen. - Inputs: 1. cursor pointing to picture records of xophoto.sqlite - 2. Index into cursor """ - self.rows = rows - if index < 0: - self.display_start_index = 0 - self.origin_row = 0 - elif index >= len(rows): - self.display_start_index = len(rows) - self.pict_per_row - self.origin_row = index // self.pict_per_row - self.selected_index = index + #make sure we have the most recent list + self.rows = self.db.get_album_thumbnails(self.album_id) + + #as we fetch the thumbnails record the number for the left column display + self.db.set_album_count(self.album_id,len(self.rows)) + #protect from an empty database if len(self.rows) == 0: return - #figure out what size to paint, assuming square aspect ratio - if self.pict_per_row > 0: - #x_size = math.floor(self.screen_width/self.pict_per_row) - x_size = self.screen_width // self.pict_per_row - else: - raise PhotoException('pict_per_row was zero or negative') - if x_size > self.screen_width: - x_size = self.screen_width - if x_size > self.screen_height: - x_size = self.screen_height - y_size = x_size - self.xy_size = x_size + num_rows = int(len(self.rows) // self.pict_per_row) + 1 + self.thumbnail_world = pygame.Surface((screen_w-album_column_width-thick,self.xy_size*num_rows)) + self.thumbnail_world.fill(background_color) + y_size = self.xy_size + x_size = self.xy_size + num_pict = len(self.rows) - if num_pict > self.num_rows * self.pict_per_row: - num_pict = self.num_rows * self.pict_per_row - self.display_start_index = self.origin_row * self.pict_per_row - #check for upper bound on rows - if num_pict + self.display_start_index > len(self.rows): - num_pict = len(self.rows)-self.display_start_index - if self.last_selected: - self.last_selected.unselect() - self.last_selected = None - screen.fill((255,255,255)) - _logger.debug('displaymany in range %s,%s'%(self.display_start_index, num_pict + self.display_start_index,)) - self.display_end_index = num_pict + self.display_start_index - for i in range(self.display_start_index, self.display_end_index): + _logger.debug('display many thumbnails in range %s,%s'%(self.display_start_index, num_pict + self.display_start_index,)) + for i in range(num_pict): if not self.pict_dict.has_key(i): - self.pict_dict[i] = DisplayOne(self.rows,self.db,self.picture_surface,i) + self.pict_dict[i] = OneThumbnail(self.rows,self.db,self.thumbnail_world,i) row = i // self.pict_per_row pos_x = (i % self.pict_per_row) * x_size pos_y = (row - self.origin_row) * y_size self.pict_dict[i].position(pos_x,pos_y) #_logger.debug('calling paint with size(%s,%s) and position(%s,%s)'%(x_size,y_size,pos_x,pos_y,)) self.pict_dict[i].size(x_size,y_size) - self.pict_dict[i].paint() - screen.blit(self.picture_surface,(album_column_width,0)) - self.select_pict(self.selected_index) - + self.pict_dict[i].paint_thumbnail() + if not self.pict_dict[i].from_database: + surf = self.thumbnail_panel(self.thumbnail_world) + screen.blit(surf,(album_column_width,0)) + pygame.display.flip() + surf = self.thumbnail_panel(self.thumbnail_world) + screen.blit(surf,(album_column_width,0)) + screen.blit(self.thumbnail_world,(album_column_width,0)) + self.select_pict(self.thumb_index) + + def thumbnail_panel(self,world): + #modeled after ezscrollbar example + scrollRect = pygame.Rect(screen_w - album_column_width - thick, 0, screen_w-album_column_width-sb_padding, screen_h) + excludes = ((0, 0), (screen_w-album_column_width-thick,screen_h)) # rect where sb update is a pass + group = pygame.sprite.RenderPlain() + self.sb = ScrollBar( + group, + world.get_height(), + scrollRect, + self.thumbnail_surface, + 1, + excludes, + 4, + False, + thick, + #(170,220,180), + (255,255,255), + (200,210,225), + (240,240,250), + (0,55,100)) + self.sb.draw(self.thumbnail_surface) + self.thumbnail_surface.blit(world, (album_column_width,0),(self.sb.get_scrolled(),(screen_w-album_column_width-thick,screen_h))) + return self.thumbnail_surface + def clear(self): - #self.picture_surface = pygame.Surface((self.screen_width,self.screen_height)) + #self.thumbnail_world = pygame.Surface((self.screen_width,self.screen_height)) self.pict_dict = {} - self.picture_surface.fill(background_color) - screen.blit(self.picture_surface,(album_column_width,0)) + if not self.thumbnail_world: return + self.thumbnail_world.fill(background_color) + screen.blit(self.thumbnail_world,(album_column_width,0)) + + def one_album_image(self,rows,index,selected=False,image_id=None): + """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 + """ + surf = pygame.Surface((album_column_width,album_height)) + + if image_id: + self.jobject_id = image_id + if selected: + surf.fill(album_selected_color) + else: + surf.fill(album_background_color) + album_id = rows[index]['subcategory'] + count = rows[index]['seq'] + album = rows[index]['jobject_id'] + + if album_id == trash_id: + if count > 0: + fn = os.path.join('assets','trash_full.png') + else: + fn = os.path.join('assets','trash_empty.png') + else: + fn = os.path.join('assets','stack_background.png') + stack = pygame.image.load(fn) + frame = pygame.transform.scale(stack,album_size) + stack_image = self.put_image_on_stack(album_id) + if stack_image: + frame.blit(stack_image,album_location) + surf.blit(frame,(0,0)) + font = pygame.font.Font(None,album_font_size) + text = font.render('%s %s'%(album,count),0,text_color) + text_rect = text.get_rect() + text_rect.midbottom = surf.get_rect().midbottom + surf.blit(text,text_rect) + _logger.debug('one album %s'%album) + return surf + + def put_image_on_stack(self,album_id): + if album_id == journal_id: + sql = "select * from groups where category = '%s' order by seq asc"%(album_id) + else: + sql = "select * from groups where category = '%s' order by seq desc"%(album_id) + (rows,cur) = self.db.dbdo(sql) + if len(rows)>0: + jobject_id = str(rows[0]['jobject_id']) + else: + jobject_id = None + _logger.debug('failed to get jobject_id:%s for display on album side (stack).sql:%s'%(jobject_id,sql,)) + return None + conn = self.db.get_connection() + cursor = conn.cursor() + cursor.execute('select * from data_cache.transforms where jobject_id = ?',(jobject_id,)) + rows = cursor.fetchall() + if len(rows) > 0: + row = rows[0] + w = row['scaled_x'] + h = row['scaled_y'] + blob =row['thumb'] + surf = pygame.image.frombuffer(blob,(w,h),'RGB') + transform_max = max(w,h) + #_logger.debug('transform rec max: %s request max: %s'%(transform_max,max_dim,)) + ret = pygame.transform.scale(surf,album_aperature) + return ret + + def set_top_image(self,jobject_id): + self.jobject_id = jobject_id + def click(self,x,y): #first determine if the x,y pair are within the displayed thumbnails thumb_index = int((y // self.xy_size) * self.pict_per_row + \ (x - album_column_width) // self.xy_size) + self.display_start_index if thumb_index <= self.display_end_index: - self.selected_index = thumb_index - self.select_pict(self.selected_index) + self.thumb_index = thumb_index + self.select_pict(self.thumb_index) def get_jobject_id_at_xy(self,x,y): #first determine if the x,y pair are within the displayed thumbnails thumb_index = int((y // self.xy_size) * self.pict_per_row + (x - album_column_width) // self.xy_size) if thumb_index <= self.display_end_index: return self.rows[thumb_index]['jobject_id'] - return None - + return + def toggle(self,x,y): if not self.large_displayed: self.large_displayed = True #restore the number of rows self.num_rows_save = self.num_rows self.num_rows = 1 - self.origin_row = self.selected_index // self.pict_per_row - self.picture_surface.fill(background_color) + self.origin_row = self.thumb_index // self.pict_per_row + self.thumbnail_world.fill(background_color) self.one_large() else: self.large_displayed = False self.num_rows = self.num_rows_save - self.picture_surface.fill(background_color) + self.thumbnail_world.fill(background_color) #following call paints the thumnails - self.paint(self.rows) + self.paint() def one_large(self): #clear the pictures - #self.picture_surface.fill(background_color) + #self.thumbnail_world.fill(background_color) #figure out what size to paint y_size = screen_h - self.xy_size x_pos = (screen_w - album_column_width - y_size) / 2 - disp_one = DisplayOne(self.rows,self.db,self.picture_surface,self.selected_index) + disp_one = OneThumbnail(self.rows,self.db,self.thumbnail_world,self.thumb_index) disp_one.position(x_pos,self.xy_size) disp_one.size(y_size,y_size) - disp_one.paint() + disp_one.paint_thumbnail() #this one will be larger than a thumbnail def screen_width(self,width): self.screen_width = width @@ -362,44 +467,44 @@ class DisplayMany(): self.last_selected = self.pict_dict[num].select() if self.large_displayed: self.one_large() - screen.blit(self.picture_surface,(album_column_width,0)) + screen.blit(self.thumbnail_world,(album_column_width,0)) def next(self): - if self.selected_index < len(self.rows)-1: - self.selected_index += 1 - #self.display_start_index = self.selected_index - if self.selected_index >= (self.origin_row + self.num_rows) * self.pict_per_row: + if self.thumb_index < len(self.rows)-1: + self.thumb_index += 1 + #self.display_start_index = self.thumb_index + if self.thumb_index >= (self.origin_row + self.num_rows) * self.pict_per_row: self.origin_row += 1 - self.paint(self.rows,self.selected_index) - self.select_pict(self.selected_index) + self.paint() + self.select_pict(self.thumb_index) def next_row(self): - if self.selected_index // self.pict_per_row < len(self.rows) // self.pict_per_row: - self.selected_index += self.pict_per_row - if self.selected_index > len(self.rows)-1: - self.selected_index = len(self.rows)-1 - if self.selected_index >= (self.origin_row + self.num_rows) * self.pict_per_row: + if self.thumb_index // self.pict_per_row < len(self.rows) // self.pict_per_row: + self.thumb_index += self.pict_per_row + if self.thumb_index > len(self.rows)-1: + self.thumb_index = len(self.rows)-1 + if self.thumb_index >= (self.origin_row + self.num_rows) * self.pict_per_row: self.origin_row += 1 - self.paint(self.rows,self.selected_index) + self.paint() self.last_selected = None - self.select_pict(self.selected_index) + self.select_pict(self.thumb_index) def prev(self): - if self.selected_index > 0: - self.selected_index -= 1 - if self.selected_index < (self.origin_row) * self.pict_per_row: + if self.thumb_index > 0: + self.thumb_index -= 1 + if self.thumb_index < (self.origin_row) * self.pict_per_row: self.origin_row -= 1 - self.paint(self.rows, self.selected_index) - self.select_pict(self.selected_index) + self.paint() + self.select_pict(self.thumb_index) def prev_row(self): - if self.selected_index // self.pict_per_row > 0: - self.selected_index -= self.pict_per_row - if self.selected_index // self.pict_per_row < self.origin_row: + if self.thumb_index // self.pict_per_row > 0: + self.thumb_index -= self.pict_per_row + if self.thumb_index // self.pict_per_row < self.origin_row: self.origin_row -= 1 - self.paint(self.rows,self.selected_index) - self.select_pict(self.selected_index) + self.paint() + self.select_pict(self.thumb_index) class DisplayAlbums(): @@ -407,27 +512,33 @@ class DisplayAlbums(): journal_id = '20100521T10:42' trash_id = '20100521T11:40' predefined_albums = [(journal_id,_('Journal')),(trash_id,_('Trash')),] #_('Duplicates'),_('Last Year'),_('Last Month'),] - journal_name = _('Journal') def __init__(self,db,activity): + """ global album_column_width global thick global background_color global album_background_color global album_selected_color + """ + + #why both _rows and _objects? + # rows is returned from a select in seq order + # objects is storage for local context and paint yourself functionality + # objects dictionary is accessed via album_id datetime stamp self.album_rows = [] + self.album_objects = {} self.album_column_width = album_column_width self.db = db #pointer to the open database self._activity = activity #pointer to the top level activity self.accumulation_target,id = self.db.get_last_album() - self.disp_many = DisplayMany(self.db) + #self.disp_many = DisplayMany(self.db) + self.default_name = _("Unnamed Photos") self.num_of_last_rolls = 5 - self.text_color = (0,0,200) self.selected_color = album_selected_color self.background_color = album_background_color - self.album_height = 190 - self.album_font_size = 30 - self.up_down_jump = 5 - self.selected_index = 0 + self.album_height = album_height + self.album_index = 0 + self.selected_album_id = journal_id #figure out how many albums can be displayed if screen_h == 0: _logger.debug('screen height not initialized') @@ -438,7 +549,6 @@ class DisplayAlbums(): self.album_surface.fill(background_color) #if the albums table is empty, populate it from the journal, and initialize - self.conn = self.db.get_connection() sql = "select * from groups" rows,cur = self.db.dbdo(sql) i = 0 @@ -448,20 +558,8 @@ class DisplayAlbums(): sql = """insert into groups (category,subcategory,jobject_id,seq) \ values ('%s','%s','%s',%s)"""%('albums',album_tup[0],album_tup[1],i,) self.db.dbtry(sql) - i += 1 + i += 20 self.db.commit() - """ - #following block is just to debug the situation where there are more albums than fit in one column - #this wont be necessary if I use scroll bar - if len(rows) < 15: #it is not long enough - conn = self.db.get_connection() - cursor = conn.cursor() - for j in range(15): - album = 'Camera Roll %s'%j - sql = "insert into groups (category,subcategory,jobject_id,seq) values ('%s','%s','%s',%s)"%('albums',album,'',i,) - cursor.execute(sql) - self.db.commit() - """ #then put the journal picutres into the journal album rows, cur = self.db.dbdo('select * from picture') i = 0 @@ -472,25 +570,28 @@ class DisplayAlbums(): sql = """insert into groups (category,subcategory,jobject_id,seq) \ values ('%s','%s','%s',%s)"""% (self.predefined_albums[0][0],self.predefined_albums[0][1],row['jobject_id'],i,) cursor.execute(sql) - i += 1 + i += 20 conn.commit() + #initialize the list of album objects from the database + album_rows = self.db.get_albums() + _logger.debug('initializing albums. %s found'%len(album_rows)) + for row in album_rows: + id = str(row['subcategory']) + self.album_objects[id] = OneAlbum(self.db,id) #the initial screen will show the contents of the journal self.display_journal() - def display_thumbnails(self,album): + def display_thumbnails(self,album_id): """uses the album (a datetime str) as value for category in table groups to display thumbnails on the right side of screen""" - sql = """select pict.*, grp.* from picture as pict, groups as grp \ - where grp.category = ? and grp.jobject_id = pict.jobject_id order by create_date desc""" - cursor = self.conn.cursor() - cursor.execute(sql,(str(album),)) - rows = cursor.fetchall() - _logger.debug('album to display: %s. Number of pictures found: %s'%(album,len(rows),)) - self.db.set_album_count(album,len(rows)) - self.disp_many.clear() - self.disp_many.last_selected = None - self.disp_many.paint(rows) + self.album_objects[self.selected_album_id].clear() + self.album_objects[self.selected_album_id].last_selected = None + alb_object = self.album_objects.get(self.selected_album_id) + if alb_object: + alb_object.paint() + else: + _logger.debug('display_thumbnails did not find %s'%album_id) def display_journal(self): self.display_thumbnails(self.journal_id) @@ -499,48 +600,10 @@ class DisplayAlbums(): global album_background_color self.album_surface.fill(album_background_color) - def can_go_up(self): - if album_display_start > 0: - return True - return False - - def can_go_down(self): - if album_display_start < self.number_of_albums - self.up_down_jump: - return True - return False - def one_album(self,rows,index,selected=False): - """album is title stored in config.jobject_id where category='albums'""" - surf = pygame.Surface((self.album_column_width,self.album_height)) - - if selected: - surf.fill(self.selected_color) - else: - surf.fill(self.background_color) - album_id = rows[index]['subcategory'] - count = rows[index]['seq'] - album = rows[index]['jobject_id'] - - if album_id == self.trash_id: - if count > 0: - fn = os.path.join('assets','trash_full.png') - else: - fn = os.path.join('assets','trash_empty.png') - else: - fn = os.path.join('assets','stack_background.png') - stack = pygame.image.load(fn) - frame = pygame.transform.scale(stack,(180,155)) - surf.blit(frame,(0,0)) - font = pygame.font.Font(None,self.album_font_size) - text = font.render('%s %s'%(album,count),0,self.text_color) - text_rect = text.get_rect() - text_rect.midbottom = surf.get_rect().midbottom - surf.blit(text,text_rect) - _logger.debug('one album %s'%album) - return surf - def album_panel(self,world): + """modeled after ezscrollbar example""" global album_column_width global screen_h global background_color @@ -548,7 +611,7 @@ class DisplayAlbums(): global album_selected_color global thick global sb_padding - thick = 15 + #thick = 15 scrollRect = pygame.Rect(album_column_width - thick, 0, album_column_width-sb_padding, screen_h) excludes = ((0, 0), (album_column_width-thick,screen_h)) # rect where sb update is a pass group = pygame.sprite.RenderPlain() @@ -572,25 +635,26 @@ class DisplayAlbums(): return self.album_surface def paint_albums(self): - global album_display_start global album_column_width screen_row = 0 - if not self.album_rows: - self.refresh_album_rows() + self.refresh_album_rows() if len(self.album_rows) > 0: self.clear_albums() self.world = pygame.Surface((album_column_width, 8 * self.album_height)) #len(self.album_rows) * self.album_height)) self.world.fill(album_background_color) - #the logic for albums is very similar to the paint many thumbnails above num_albums = len(self.album_rows) for row_index in range(num_albums ): - selected = (row_index == self.selected_index) - self.world.blit(self.one_album(self.album_rows, row_index, selected),(0,screen_row * self.album_height)) + selected = (row_index == self.album_index) + album_id = self.album_rows[row_index]['subcategory'] + album_object = self.album_objects[album_id] + album_image = album_object.one_album_image(self.album_rows, row_index, selected) + self.world.blit(album_image,(0,screen_row * self.album_height)) screen_row += 1 surf = self.album_panel(self.world) - screen.blit(surf, (0,0)) - + screen.blit(surf, (0,0)) + pygame.display.flip() + def refresh_album_rows(self): sql = "select * from groups where category = 'albums' order by id" rows,cur = self.db.dbdo(sql) @@ -600,17 +664,24 @@ class DisplayAlbums(): def click(self,x,y): """select the pointed to item""" - global album_display_start #get the y index - y_index = y // self.album_height - self.selected_index = y_index + album_display_start + sb_x,sb_y = self.sb.get_scrolled() + y_index = (y + sb_y) // self.album_height + self.album_index = int(y_index) + self.accumulation_target = self.album_index + self.refresh_album_rows() + if self.album_index >= len(self.album_rows) : + return None + #now change the thumbnail side of the screen try: - album_name = self.album_rows[int(self.selected_index)]['subcategory'] - album_title = self.album_rows[int(self.selected_index)]['jobject_id'] + album_name = self.album_rows[int(self.album_index)]['subcategory'] + album_title = self.album_rows[int(self.album_index)]['jobject_id'] except Exception,e: album_name = journal_id #the journal _logger.debug('exception fetching thumbnails %s'%e) + return + self.selected_album_id = album_name _logger.debug('now display the thumbnails with the album identifier %s'%album_name) self._activity.activity_toolbar.title.set_text(album_title) self.display_thumbnails(album_name) @@ -626,48 +697,75 @@ class DisplayAlbums(): --seq = modified as the order of the pictures is modified (seq = count of albums when category='albums') """ - if not name: name = _("Unnamed Photos") + if not name: name = self.default_name self.accumulation_target,id = self.db.get_last_album() + if not self.album_objects.has_key(self.accumulation_target): + self.accumulation_target = None _logger.debug('last album id was %s and id was %s'%(self.accumulation_target,id)) if not self.accumulation_target: - self.create_new_album() + self.create_new_album(name) else: #see if this is a request to change name if jobject_id == '': - jobject_id = self.accumulation_target + jobject_id = self.accumulation_target self.db.add_image_to_album(self.accumulation_target, jobject_id) + self.album_objects[self.accumulation_target].set_top_image(self.accumulation_target) #self.display_thumbnails(self.accumulation_target) - self.refresh_album_rows() self.paint_albums() - def create_new_album(self): - self.accumulation_target = str(datetime.datetime.today()) - _logger.debug('new album is:%s'%self.accumulation_target) - self.db.create_update_album(self.accumulation_target,name) + def set_name(self,name): + self.db.create_update_album(self.album_rows[self.album_index]['subcategory'],name) + self.paint_albums() + pygame.display.flip() + + + def create_new_album(self,name): + if not name: name = self.default_name + self.accumulation_target = str(datetime.datetime.today()) + _logger.debug('new album is:%s'%self.accumulation_target) + self.db.create_update_album(self.accumulation_target,name) + self.album_objects[self.accumulation_target] = (OneAlbum(self.db,self.accumulation_target)) + #save off the unique id(timestamp)as a continuing target + self.db.set_last_album(self.accumulation_target) + self.paint_albums() - #save off the unique id(timestamp)as a continuing target - self.db.set_last_album(self.accumulation_target) + def delete_album(self,album_id): + _logger.debug('delete album action routine. deleting id(timestamp):%s'%album_id) + """ need to delete the album pointer, the album records, and album object""" + if self.album_objects.has_key(album_id): + del self.album_objects[album_id] + conn = self.db.get_connection() + cursor = conn.cursor() + cursor.execute('delete from groups where subcategory = ?',(str(album_id),)) + cursor.execute('delete from groups where category = ?',(str(album_id),)) + conn.commit() + self.album_index = 0 + self.selected_album_id = self.journal_id + self.display_thumbnails(self.selected_album_id) + self.paint_albums() + def change_name_of_current_album(self,name): """create a 'current' album (if necessary) and name it""" self.add_to_current_album('',name) def get_current_album_identifier(self): - return self.album_rows[self.selected_index]['subcategory'] + return str(self.album_rows[self.album_index]['subcategory']) def get_current_album_name(self): - return self.album_rows[self.selected_index]['jobject_id'] + return str(self.album_rows[self.album_index]['jobject_id']) def get_album_index_at_xy(self,x,y): if x > album_column_width - thick: return None index = y // self.album_height - if index > len(self.album_rows): return None return int(index) def add_to_album_at_xy(self,x,y): - jobject_id = self.disp_many.get_jobject_id_at_xy(x,y) + jobject_id = self.album_objects[self.selected_album_id].get_jobject_id_at_xy(x,y) if jobject_id: self.add_to_current_album(jobject_id) + else: + _logger.debug('could not find jobject_id in add_to_aqlbum_at_xy') def start_grab(self,x,y): self.start_grab_x = x @@ -678,15 +776,38 @@ class DisplayAlbums(): def drop_image(self, img_x,img_y,album_x, album_y): self._activity.window.set_cursor(None) index = self.get_album_index_at_xy(album_x, album_y) - jobject_id = self.disp_many.get_jobject_id_at_xy(img_x,img_y) + jobject_id = self.album_objects[self.selected_album_id].get_jobject_id_at_xy(img_x,img_y) if not index or not jobject_id: return #if index is larger than max, we want a new album - if index > len(self.album_rows): - self.create_new_album() + _logger.debug('index:%s length of rows:%s jobject_id %s'%(index,len(self.album_rows),jobject_id,)) + if index > len(self.album_rows)-1: + self.create_new_album(self.default_name) + 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) + #self.display_thumbnails(self.accumulation_target) + self.refresh_album_rows() + self.paint_albums() + + def toggle(self,x,y): + """change the number of albums displayed""" + pass + + + def roll_over(self,x,y, in_drag=False): + """indicate willingness to be selected""" + pass + + def do_drag_up(self,x,y): + """add the dragged item to the selected album""" + pass + + ##################### ALERT ROUTINES ################################## +class Utilities(): + def __init__(self,activity): + self._activity = activity def alert(self,msg,title=None): alert = NotifyAlert(0) @@ -699,7 +820,8 @@ class DisplayAlbums(): def no_file_cb(self,alert,response_id): self._activity.remove_alert(alert) - + pygame.display.flip + from sugar.graphics.alert import ConfirmationAlert def confirmation_alert(self,msg,title=None,confirmation_cb = None): @@ -708,7 +830,7 @@ class DisplayAlbums(): alert.props.msg = msg alert.callback_function = confirmation_cb alert.connect('response', self._alert_response_cb) - self.add_alert(alert) + self._activity.add_alert(alert) return alert #### Method: _alert_response_cb, called when an alert object throws a @@ -717,30 +839,12 @@ class DisplayAlbums(): #remove the alert from the screen, since either a response button #was clicked or there was a timeout this_alert = alert #keep a reference to it - self.remove_alert(alert) + self._activity.remove_alert(alert) + pygame.display.flip() #Do any work that is specific to the type of button clicked. if response_id is gtk.RESPONSE_OK and this_alert.callback_function != None: this_alert.callback_function (this_alert, response_id) - def toggle(self,x,y): - """change the number of albums displayed""" - pass - - - def roll_over(self,x,y, in_drag=False): - """indicate willingness to be selected""" - pass - - def do_drag_up(self,x,y): - """add the dragged item to the selected album""" - pass - - def add_new_album(self,name): - pass - - def delete_album(self,x,y): - pass - class Application(): #how far does a drag need to be not to be ignored? @@ -761,8 +865,15 @@ class Application(): self.file_tree.copy_tree_to_ds(source) number_of_pictures = self.ds_sql.scan_images() if number_of_pictures < 10: - _logger.debug('failed to initalize the datastore with at least 10 pictures') - + _logger.debug('failed to initalize the datastore with at least 10 pictures') + + def change_album_name(self,name): + if self.album_collection: + self.album_collection.set_name(name) + + def pygame_display(self): + pygame.display.flip() + def run(self): global screen global in_click_delay @@ -773,7 +884,7 @@ class Application(): if True: #moved the database functionality here because of sync problems with journal if not self._activity.DbAccess_object: #we need to wait for the read-file to finish - Timer(25.0, self.end_db_delay, ()).start() + 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() @@ -818,14 +929,15 @@ class Application(): screen.fill((255,255,255)) #255 for white x = 0 pygame.display.flip() - + self.util = Utilities(self._activity) + #self.util.alert("this is a test") #if the picture table is empty, populate it from the journal, and initialize if ds_count < 10: self.first_run_setup() - self.albums = DisplayAlbums(self.db, self._activity) - self.albums.paint_albums() + self.album_collection = DisplayAlbums(self.db, self._activity) + self.album_collection.paint_albums() # Flip Display pygame.display.flip() @@ -849,16 +961,16 @@ class Application(): running = False pygame.quit() elif event.key == K_LEFT: - self.albums.disp_many.prev() + self.album_collection.album_objects[self.album_collection.selected_album_id].prev() pygame.display.flip() elif event.key == K_RIGHT: - self.albums.disp_many.next() + self.album_collection.album_objects[self.album_collection.selected_album_id].next() pygame.display.flip() elif event.key == K_UP: - self.albums.disp_many.prev_row() + self.album_collection.album_objects[self.album_collection.selected_album_id].prev_row() pygame.display.flip() elif event.key == K_DOWN: - self.albums.disp_many.next_row() + self.album_collection.album_objects[self.album_collection.selected_album_id].next_row() pygame.display.flip() #mouse events @@ -881,12 +993,12 @@ class Application(): pygame.display.set_mode(event.size, pygame.RESIZABLE) if x < album_column_width: - self.albums.sb.update(event) - changes = self.albums.sb.draw(self.albums.album_surface) + self.album_collection.sb.update(event) + changes = self.album_collection.sb.draw(self.album_collection.album_surface) if len(changes) > 0: - changes.append(self.albums.album_surface.blit(self.albums.world, (0,0), - (self.albums.sb.get_scrolled(),(album_column_width-thick,screen_h)))) - screen.blit(self.albums.album_surface,(0,0)) + changes.append(self.album_collection.album_surface.blit(self.album_collection.world, (0,0), + (self.album_collection.sb.get_scrolled(),(album_column_width-thick,screen_h)))) + screen.blit(self.album_collection.album_surface,(0,0)) pygame.display.update(changes) @@ -915,7 +1027,7 @@ class Application(): return print('drop at %s,%s'%(x,y,)) if in_drag and self.last_l: - self.albums.drop_image(self.drag_start_x,self.drag_start_y,x,y) + self.album_collection.drop_image(self.drag_start_x,self.drag_start_y,x,y) pygame.display.flip() def process_mouse_click(self,event): @@ -923,21 +1035,24 @@ class Application(): l,m,r = pygame.mouse.get_pressed() print('mouse single click') if x < album_column_width -thick: - scroll_x,scroll_y = self.albums.sb.get_scrolled() - self.albums.click(x,y + scroll_y) + scroll_x,scroll_y = self.album_collection.sb.get_scrolled() + rtn_val = self.album_collection.click(x,y + scroll_y) + if not rtn_val: + #create a new album + pass elif x > album_column_width: if l: - self.albums.disp_many.click(x,y) + self.album_collection.album_objects[self.album_collection.selected_album_id].click(x,y) elif r: self.in_grab = True - self.albums.start_grab(x,y) + self.album_collection.start_grab(x,y) pygame.display.flip() def process_mouse_double_click(self,event): x,y = event.pos print('double click') if x > album_column_width: - self.albums.add_to_album_at_xy(x,y) + self.album_collection.add_to_album_at_xy(x,y) pygame.display.flip() def mouse_timer_running(self): diff --git a/photo_toolbar.py b/photo_toolbar.py index 16fec38..3903c3d 100644 --- a/photo_toolbar.py +++ b/photo_toolbar.py @@ -47,7 +47,7 @@ class ActivityToolbar(gtk.Toolbar): """ #if activity.metadata: if True: - label = gtk.Label(_('New Album Name:')) + label = gtk.Label(_('New Album Name: ')) label.show() self._add_widget(label) @@ -56,7 +56,8 @@ class ActivityToolbar(gtk.Toolbar): if activity.metadata: self.title.set_text(activity.metadata['title']) #activity.metadata.connect('updated', self.__jobject_updated_cb) - #self.title.connect('changed', self.__title_changed_cb) + self.title.connect('changed', self.__title_changed_cb) + self.title.connect('activate', self.__update_title_cb) self._add_widget(self.title) self.add_album = ToolButton('list-add') @@ -168,18 +169,20 @@ class ActivityToolbar(gtk.Toolbar): self._update_title_sid = gobject.timeout_add_seconds( 1, self.__update_title_cb) - def __update_title_cb(self): + def __update_title_cb(self, entry=None): title = self.title.get_text() self._activity.metadata['title'] = title self._activity.metadata['title_set_by_user'] = '1' - self._activity.save() - + self._activity.game.change_album_name(title) + #self._activity.save() + """ shared_activity = self._activity.get_shared_activity() if shared_activity: shared_activity.props.name = title - + """ self._update_title_sid = None + return False def _add_widget(self, widget, expand=False): @@ -78,24 +78,28 @@ class Datastore_SQLite(): return rtn def check_for_recent_images(self): - """scans the journal for pictures that are not in database, records object_id if found""" - find_spec = {'mime_type':['image/png','image/jpg','image/tif','image/bmp','image/gif']} - (results,count) = datastore.find(find_spec) - _logger.debug('directed image datastore found:%s'%count) + """scans the journal for pictures that are not in database, records object_id if found. + stops checking when the first image is found that is already in the database. + """ + mime_list = self.db.get_mime_list() + (results,count) = datastore.find({}) + _logger.debug('Journal/datastore entries found:%s'%count) added = 0 a_row_found = False cursor = self.db.get_connection().cursor() for ds in results: #at least for now assume that the newest images are returned first if not a_row_found: - cursor.execute('select * from picture where jobject_id = ?',(str(ds.object_id),)) - rows = cursor.fetchall() - if len(rows) == 0: - #may need to add date entered into ds (create date could be confusing) - self.db.put_ds_into_picture(ds.object_id) - added += 1 - else: #assume that pictures are returned in last in first out order - a_row_found = True + dict = ds.get_metadata().get_dictionary() + if dict["mime_type"] in mime_list: + cursor.execute('select * from picture where jobject_id = ?',(str(ds.object_id),)) + rows = cursor.fetchall() + if len(rows) == 0: + #may need to add date entered into ds (create date could be confusing) + self.db.put_ds_into_picture(ds.object_id) + added += 1 + else: #assume that pictures are returned in last in first out order + a_row_found = True ds.destroy() _logger.debug('added %s datastore object ids from datastore to picture'%added) return (count,added,) diff --git a/sugargame/canvas.py b/sugargame/canvas.py index abaa0eb..e38508d 100644 --- a/sugargame/canvas.py +++ b/sugargame/canvas.py @@ -46,25 +46,14 @@ class PygameCanvas(gtk.EventBox): translator.hook_pygame() # Restore the default cursor. - from threading import Timer - self.window_timer = False - Timer(10.0, self.end_window_delay, ()).start() - while not self.window_timer: - gtk.main_iteration() - if hasattr(self._socket,'get_window'): # or hasattr(self._socket.get_window(),'realized'): - break - if self.window_timer: - _logger.debug('gtk window not visible through socket') - exit() - self._socket.get_window().set_cursor(None) - + #self._socket.get_window().set_cursor(None) + window = self._socket.get_parent_window() + window.set_cursor(None) + # Run the Pygame main loop. main_fn() return False - def end_window_delay(self): - self.window_timer = True - def get_pygame_widget(self): return self._socket diff --git a/xophoto.sqlite.template b/xophoto.sqlite.template Binary files differindex b66fb47..11c5721 100644 --- a/xophoto.sqlite.template +++ b/xophoto.sqlite.template diff --git a/xophotoactivity.py b/xophotoactivity.py index f117e0d..0f74397 100644 --- a/xophotoactivity.py +++ b/xophotoactivity.py @@ -46,6 +46,7 @@ from threading import Timer from subprocess import Popen, PIPE import display +from display import * import photo_toolbar from sources import * from sinks import * @@ -76,6 +77,8 @@ class XoPhotoActivity(activity.Activity): self.window_realized = False self.game = None self.kept_once = False + self.util = Utilities(self) + if handle and handle.object_id and handle.object_id != '' and not self.use_db_template: _logger.debug('At activity startup, handle.object_id is %s'%handle.object_id) @@ -172,19 +175,23 @@ class XoPhotoActivity(activity.Activity): def activity_toolbar_add_album_cb(self,album_name): - self.game.albums.change_name_of_current_album(album_name ) + self.game.album_collection.create_new_album(None) def activity_toolbar_delete_album_cb(self): - album = self.game.albums.get_current_album_name() - self.game.albums.alert('Are you sure you want to delete %s?'%album) + album = self.game.album_collection.get_current_album_name() + album_id = self.game.album_collection.get_current_album_identifier() + if album_id in [journal_id,trash_id]: + self.util.alert(_('Drag pictures to the Trash, and then empty the trash'),\ + _('Warning! Journal and Trash cannot be deleted')) + return + self.util.confirmation_alert(_('Are you sure you want to delete %s?')%album,\ + _('Caution'),self.confirm_delete_album_cb) - def confirm_delete_album_cb(self,response): - album = self.game.albums.get_current_album_identifier() - - if not response in (gtk.RESPONSE_OK):return - sql = 'delete from groups where subcategory = ?' - cursor = self.game.db.conn.cursor() - cursor.execute(sql,()) + def confirm_delete_album_cb(self,alert,response): + album_id = self.game.album_collection.get_current_album_identifier() + _logger.debug('about to delete album with identifier:%s'%album_id) + if not response == gtk.RESPONSE_OK:return + self.game.album_collection.delete_album(album_id) def command_line(self,cmd, alert_error=False): _logger.debug('command_line cmd:%s'%cmd) @@ -192,7 +199,7 @@ class XoPhotoActivity(activity.Activity): output = p1.communicate() if p1.returncode != 0 : _logger.debug('error returned from shell command: %s was %s'%(cmd,output[0])) - if alert_error: self.alert(_('%s Command returned non zero\n'%cmd+output[0])) + if alert_error: self.util.alert(_('%s Command returned non zero\n'%cmd+output[0])) return output[0],p1.returncode @@ -201,6 +208,12 @@ class XoPhotoActivity(activity.Activity): dict = self.get_metadata() #set a flag to copy the template self.interactive_close = True + + #compact the database + conn = self.DbAccess_object.get_connection() + cursor = conn.cursor() + cursor.execute('vacuum') + self.save() db_path = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite') @@ -211,33 +224,40 @@ class XoPhotoActivity(activity.Activity): exit() source = db_path ds = datastore.create() - ds.metadata['title'] = _('Empty Photo Stack') + ds.metadata['title'] = _('New Photo Stack') ds.metadata['activity_id'] = dict.get('activity_id') ds.metadata['activity'] = 'org.laptop.XoPhoto' ds.metadata['mime_type'] = 'application/binary' dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'instance','xophoto.sqlite') + + #albums are stored in the groups table, so start fresh + conn = self.DbAccess_object.get_connection() + cursor = conn.cursor() + cursor.execute("delete from groups") + conn.commit() + shutil.copyfile(source,dest) ds.set_file_path(dest) datastore.write(ds,transfer_ownership=True) ds.destroy() - if dict.get('dbcorrupted','False') == 'False' and not self.kept_once: - #try to save all the time/computation involved in making thumbnails - backup_db = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto_back.sqlite') - if os.path.isfile(backup_db): - try: - conn = self.DbAccess_object.get_connection() - cursor = conn.cursor() - cursor.execute("attach '%s' as thumbs"%backup_db) - sql = 'insert into picture select * from thumbs.picture' - cursor.execute(sql) - sql = 'insert into transforms select * from thumbs.transforms' - cursor.execute(sql) - conn.commit() - except Exception,e: - _logger.debug('database exception %s'%e) - raise e - self.kept_once = True - self.game.albums.alert(_('Click KEEP again for a completely new Database.'),_('New Database initialized from the Current Database.')) + + #check the thumbnails + cursor.execute('pragma data_cache.quick_check') + rows = cursor.fetchall() + if len(rows) == 1 and str(rows[0]) == 'ok': + #thumbnails database is ok + _logger.debug('thumbnail database passes quick_check') + else: + #need to start over with a new template and regenerate the thumbnails + _logger.debug('swapping in template for transforms (thumbnail) database') + + try: + source = os.path.join(os.getcwd(),'data_cache.sqlite.template') + local_path = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','data_cache.sqlite') + shutil.copy(source,local_path) + except Exception,e: + _logger.debug('data_cache template failed to copy error:%s'%e) + exit() def edit_toolbar_doimport_cb(self, view_toolbar): if not self.file_tree: @@ -284,6 +304,7 @@ class XoPhotoActivity(activity.Activity): _logger.debug('started read_file %s. make_file flag %s'%(file_path,self.make_jobject)) if self.make_jobject: #make jobject is flag signifying that we are not resuming activity _logger.debug(' copied template rather than resuming') + #This is a new invocation, copy the sqlite database to the data directory source = os.path.join(os.getcwd(),'xophoto.sqlite.template') dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite') @@ -292,6 +313,16 @@ class XoPhotoActivity(activity.Activity): except Exception,e: _logger.debug('database template failed to copy error:%s'%e) exit() + + #now do the same for the thumbnails if they don't already exist + source = os.path.join(os.getcwd(),'data_cache.sqlite.template') + dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','data_cache.sqlite') + if not os.path.isfile(dest): + try: + shutil.copy(source,dest) + except Exception,e: + _logger.debug('thumbnail database template failed to copy error:%s'%e) + exit() else: if self.DbAccess_object: #if the database is open don't overwrite and confuse it _logger.debug('in read-file, db was already open') |