diff options
author | George Hunt <ghunt@ghunt-desktop.(none)> | 2010-06-09 14:22:15 (GMT) |
---|---|---|
committer | George Hunt <ghunt@ghunt-desktop.(none)> | 2010-06-09 14:22:15 (GMT) |
commit | 3dd64e23f215a7388982cf8560d58d1fdb4ae4ed (patch) | |
tree | 96a0999dfd32cc85bc29c8aac60e176c8df0363c | |
parent | 1c910a6a53ee169e2792588049e2d1be7115a082 (diff) |
drag/drop, trash icons, album interactions
-rw-r--r-- | dbphoto.py | 49 | ||||
-rw-r--r-- | display.py | 142 | ||||
-rw-r--r-- | photo_toolbar.py | 4 | ||||
-rw-r--r-- | startup_images/XoPhoto.svg | 54 | ||||
-rw-r--r-- | startup_images/trash_empty.png | bin | 0 -> 64751 bytes | |||
-rw-r--r-- | startup_images/trash_full.png | bin | 0 -> 75031 bytes | |||
-rw-r--r-- | xophotoactivity.py | 10 |
7 files changed, 195 insertions, 64 deletions
@@ -183,7 +183,54 @@ class DbAccess(): else: cursor.execute("insert into config (name,value) values (?,?)",('last_album',album_id)) self.con.commit() - + + def set_album_count(self,album_id,count): + cursor = self.con.cursor() + cursor.execute("select * from groups where category = 'albums' and subcategory = ?",(str(album_id),)) + rows = cursor.fetchmany() + if len(rows) == 1: + try: + cursor.execute('update groups set seq = ? where id = ?',(count,rows[0]['id'])) + self.con.commit() + except Exception,e: + _logger.debug('set album count error:%s'%e) + + def get_album_count(self,album_id): + cursor = self.con.cursor() + try: + cursor.execute("select * from groups where category = 'albums' and subcategory = ?",(str(album_id,))) + rows = cursor.fetchmany() + if len(rows) == 1: + return rows[0]['seq'] + return 0 + except: + return 0 + + def create_update_album(self,album_id,name): + cursor = self.con.cursor() + cursor.execute('select * from groups where category = ? and subcategory = ?',\ + ('albums',str(album_id,))) + rows = cursor.fetchmany() + if len(rows)>0 : #pick up the name + id = rows[0]['id'] + cursor.execute("update groups set category = ?, subcategory = ?, jobject_id = ? where id = ?",\ + (str(album_id),name,id)) + else: + cursor.execute("insert into groups (category,subcategory,jobject_id,seq) values (?,?,?,?)",\ + ('albums',str(album_id),name,0)) + self.con.commit() + + def add_image_to_album(self, album_id, jobject_id): + cursor = self.con.cursor() + #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)) + self.con.commit() + def table_exists(self,table): try: sql = 'select * from %s'%table @@ -273,7 +273,8 @@ class DisplayMany(): #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 - self.last_selected.unselect() + 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,)) @@ -295,10 +296,13 @@ class DisplayMany(): #self.picture_surface = 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)) + 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) + 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) @@ -353,6 +357,7 @@ class DisplayMany(): def select_pict(self,num): if self.last_selected: self.last_selected.unselect() + if not self.pict_dict.has_key(num): return self.last_selected = self.pict_dict[num].select() if self.large_displayed: self.one_large() @@ -398,11 +403,13 @@ class DisplayMany(): class DisplayAlbums(): """Shows the photo albums on left side of main screen, responds to clicks, drag/drop events""" - - predefined_albums = [('20100521T10:42',_('Journal')),('20100521T11:40',_('Trash')),] #_('Duplicates'),_('Last Year'),_('Last Month'),] + 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 @@ -471,19 +478,21 @@ class DisplayAlbums(): self.display_journal() def display_thumbnails(self,album): - """uses the album as value for category in table groups to display thumbnails on the right side of screen""" + """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) def display_journal(self): - self.display_thumbnails('20100521T10:42') + self.display_thumbnails(self.journal_id) def clear_albums(self): global album_background_color @@ -499,20 +508,30 @@ class DisplayAlbums(): return True return False - def one_album(self,album,selected=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) - - fn = os.path.join('startup_images','stack_background.png') + 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('startup_images','trash_full.png') + else: + fn = os.path.join('startup_images','trash_empty.png') + else: + fn = os.path.join('startup_images','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(album,0,self.text_color) + 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) @@ -566,7 +585,7 @@ class DisplayAlbums(): 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]['jobject_id'],selected),(0,screen_row * self.album_height)) + self.world.blit(self.one_album(self.album_rows, row_index, selected),(0,screen_row * self.album_height)) screen_row += 1 surf = self.album_panel(self.world) screen.blit(surf, (0,0)) @@ -584,21 +603,15 @@ class DisplayAlbums(): #get the y index y_index = y // self.album_height self.selected_index = y_index + album_display_start - if self.number_of_albums > self.max_albums_displayed: - self.selected_index -= 1 - if self.selected_index < album_display_start and self.can_go_up(): - album_display_start -= self.up_down_jump - elif y_index == self.max_albums_displayed-1 and self.can_go_down(): - self.selected_index = album_display_start + self.max_albums_displayed - album_display_start += self.up_down_jump - self.paint_albums() #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'] except Exception,e: - album_name = '20100521T10:42' #the journal + album_name = journal_id #the journal _logger.debug('exception fetching thumbnails %s'%e) _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) def add_to_current_album(self,jobject_id,name=None): @@ -607,49 +620,32 @@ class DisplayAlbums(): NOTE: Albums are stored in the table - 'groups' as follows: --category = 'albums' --subcategory = <unique string based upon date-time album was created - --Album name = Stored in the jobject_id field + (This is then used as a value for category to get all pictures in album) + --Album name = Stored in the jobject_id field (when category = 'albums') --seq = modified as the order of the pictures is modified + (seq = count of albums when category='albums') """ - if not name: name = _("Unnamed Stack") - conn = self.db.get_connection() - cursor = conn.cursor() + if not name: name = _("Unnamed Photos") self.accumulation_target,id = self.db.get_last_album() - _logger.debug('album id was %s and id was %s'%(self.accumulation_target,id)) + _logger.debug('last album id was %s and id was %s'%(self.accumulation_target,id)) if not self.accumulation_target: self.accumulation_target = str(datetime.datetime.today()) _logger.debug('new album is:%s'%self.accumulation_target) - sql = """insert into groups (category,subcategory,jobject_id,seq) \ - values ('%s','%s','%s',%s)"""% ('albums',self.accumulation_target,name,0,) - cursor.execute(sql) - conn.commit() - + self.db.create_update_album(self.accumulation_target,name) + #save off the unique id(timestamp)as a continuing target self.db.set_last_album(self.accumulation_target) + else: #see if this is a request to change name - if jobject_id == None: - sql = 'select * from groups where category = ? and subcategory = ?' - cursor.execute(sql,('albums',self.accumulation_target)) - rows = cursor.fetchmany() - if len(rows)>0 : #pick up the name - id = rows[0]['id'] - sql = "update groups set jobject_id = ? where id = ?" - cursor.execute(sql,(name,id,)) - conn.commit() - return - #we will try to add the same picture only once - sql = "select * from groups where category = ? and jobject_id = ?" - cursor.execute(sql,(self.accumulation_target,jobject_id,)) - rows = cursor.fetchmany() - if len(rows)>0: return + if jobject_id == '': + jobject_id = self.accumulation_target + self.db.add_image_to_album(self.accumulation_target, jobject_id) - sql = """insert into groups (category,subcategory,jobject_id,seq) \ - values (?,?,?,?)""" - cursor.execute(sql,(self.accumulation_target,name,jobject_id,0,)) - self.db.commit() #self.display_thumbnails(self.accumulation_target) self.refresh_album_rows() 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) @@ -659,12 +655,31 @@ class DisplayAlbums(): def get_current_album_name(self): return self.album_rows[self.selected_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_album_at_xy(self,x,y): + def add_to_album_at_xy(self,x,y): jobject_id = self.disp_many.get_jobject_id_at_xy(x,y) if jobject_id: self.add_to_current_album(jobject_id) + def start_grab(self,x,y): + self.start_grab_x = x + self.start_grab_y = y + #change the cursor some way + self._activity.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.TOP_LEFT_CORNER)) + + 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) + if not index or not jobject_id: return + self.db.add_image_to_album(self.album_rows[index]['subcategory'], jobject_id) + ##################### ALERT ROUTINES ################################## def alert(self,msg,title=None): @@ -727,6 +742,7 @@ class Application(): db = None def __init__(self, activity): self._activity = activity + self.in_grab = False def first_run_setup(self): #scan the datastore and add new images as required @@ -745,7 +761,7 @@ class Application(): global screen_w global screen_h global in_db_wait - + global in_drag 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 @@ -868,36 +884,50 @@ class Application(): global in_drag x,y = event.pos l,m,r = pygame.mouse.get_pressed() + self.last_l = l + self.last_r = r if not l: return if not in_drag: print('drag started at %s,%s'%(x,y,)) in_drag = True #record the initial position self.drag_start_x,self.drag_start_y = x,y + elif x < album_column_width -thick: + self._activity.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.PLUS)) + def drop(self,event): + global in_drag x,y = event.pos #if the drag is less than threshold, ignore if max(abs(self.drag_start_x - x), abs(self.drag_start_y - y)) < self.drag_threshold: in_drag = False 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) pygame.display.flip() def process_mouse_click(self,event): x,y = event.pos + l,m,r = pygame.mouse.get_pressed() print('mouse single click') - if x < album_column_width: - self.albums.click(x,y) - else: - self.albums.disp_many.click(x,y) + if x < album_column_width -thick: + scroll_x,scroll_y = self.albums.sb.get_scrolled() + self.albums.click(x,y + scroll_y) + elif x > album_column_width: + if l: + self.albums.disp_many.click(x,y) + elif r: + self.in_grab = True + self.albums.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_album_at_xy(x,y) + self.albums.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 5190ddf..16fec38 100644 --- a/photo_toolbar.py +++ b/photo_toolbar.py @@ -55,8 +55,8 @@ class ActivityToolbar(gtk.Toolbar): self.title.set_size_request(int(gtk.gdk.screen_width() / 6), -1) 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) + #activity.metadata.connect('updated', self.__jobject_updated_cb) + #self.title.connect('changed', self.__title_changed_cb) self._add_widget(self.title) self.add_album = ToolButton('list-add') diff --git a/startup_images/XoPhoto.svg b/startup_images/XoPhoto.svg new file mode 100644 index 0000000..d15c7e4 --- /dev/null +++ b/startup_images/XoPhoto.svg @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 10, SVG Export Plug-In . SVG Version: 3.0.0 Build 76) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" [ + <!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/"> + <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/"> + <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/"> + <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/"> + <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/"> + <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/"> + <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/"> + <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/"> + <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/"> + <!ENTITY ns_svg "http://www.w3.org/2000/svg"> + <!ENTITY ns_xlink "http://www.w3.org/1999/xlink"> + <!ENTITY stroke_color "#666666"> + <!ENTITY fill_color "#CCCCCC"> +]> +<svg + xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;" i:viewOrigin="254.2856 419.2651" i:rulerOrigin="0 0" i:pageBounds="0 792 612 0" + xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/" + width="48.758" height="48.736" viewBox="0 0 48.758 48.736" overflow="visible" enable-background="new 0 0 48.758 48.736" + xml:space="preserve"> + <metadata> + <variableSets xmlns="http://ns.adobe.com/Variables/1.0/"> + <variableSet varSetName="binding1" locked="none"> + <variables></variables> + <v:sampleDataSets xmlns="http://ns.adobe.com/GenericCustomNamespace/1.0/" xmlns:v="http://ns.adobe.com/Variables/1.0/"> + </v:sampleDataSets> + </variableSet> + </variableSets> + <sfw xmlns="&ns_sfw;"> + <slices></slices> + <sliceSourceBounds y="370.529" x="254.286" width="48.758" height="48.736" bottomLeftOrigin="true"></sliceSourceBounds> + </sfw> + </metadata> + <g id="Layer_1" i:knockout="Off" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF"> + + <path i:knockout="Off" fill="#FFFFFF" stroke="&stroke_color;" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round" d=" + M43.07,8.245h4.139v31.833H17.866l-0.868,0.146L6.3,42.01L1.218,10.585l3.876-0.647l0.441-0.074l0.008-1.62h9.773l2.844-0.49 + l24.154-4.036l0.602,3.604L43.07,8.245z"/> + <path i:knockout="Off" fill="#FFFFFF" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" d="M46.627,39.161H6.21 + V9.245h40.417V39.161z"/> + <path i:knockout="Off" fill="&fill_color;" d="M43.627,11.578H8.96v24.75h6.433c0.092-1.765,0.24-3.677,0.48-4.591 + c0.447-1.695,4.26-4.017,8.416-4.562c-2.058-0.904-3.535-3.35-3.535-6.229c0-3.65,2.369-6.61,5.289-6.61s5.289,2.96,5.289,6.61 + c0,2.88-1.477,5.324-3.533,6.229c4.154,0.545,7.967,2.865,8.414,4.562c0.24,0.914,0.389,2.826,0.479,4.591h6.936L43.627,11.578z" + /> + <path i:knockout="Off" fill="none" stroke="&stroke_color;" stroke-width="0.5" stroke-linejoin="bevel" d="M15.392,36.328 + c0.092-1.765,0.24-3.677,0.48-4.591c0.447-1.695,4.26-4.017,8.417-4.562c-2.058-0.904-3.536-3.35-3.536-6.229 + c0-3.65,2.37-6.61,5.29-6.61s5.289,2.96,5.289,6.61c0,2.88-1.477,5.324-3.533,6.229c4.154,0.545,7.967,2.865,8.414,4.562 + c0.24,0.914,0.389,2.826,0.479,4.591"/> + <path i:knockout="Off" fill="none" stroke="&stroke_color;" stroke-width="0.5" d="M43.627,36.328H8.96v-24.75h34.667V36.328z"/> + <path i:knockout="Off" fill="none" d="M48.758,48.736H0.022V0h48.736V48.736z"/> + </g> +</svg> diff --git a/startup_images/trash_empty.png b/startup_images/trash_empty.png Binary files differnew file mode 100644 index 0000000..0aefec7 --- /dev/null +++ b/startup_images/trash_empty.png diff --git a/startup_images/trash_full.png b/startup_images/trash_full.png Binary files differnew file mode 100644 index 0000000..41764e9 --- /dev/null +++ b/startup_images/trash_full.png diff --git a/xophotoactivity.py b/xophotoactivity.py index 85828bb..f117e0d 100644 --- a/xophotoactivity.py +++ b/xophotoactivity.py @@ -132,20 +132,20 @@ class XoPhotoActivity(activity.Activity): def build_toolbar(self): toolbox = photo_toolbar.ActivityToolbox(self) - activity_toolbar = toolbox.get_activity_toolbar() + self.activity_toolbar = toolbox.get_activity_toolbar() """ label = gtk.Label(_('New Album Name:')) tool_item = gtk.ToolItem() tool_item.set_expand(False) tool_item.add(label) label.show() - activity_toolbar.insert(tool_item, 0) + self.activity_toolbar.insert(tool_item, 0) tool_item.show() - activity_toolbar._add_widget(label) + self.activity_toolbar._add_widget(label) """ - activity_toolbar.keep.props.visible = True - #activity_toolbar.share.props.visible = False + self.activity_toolbar.keep.props.visible = True + #self.activity_toolbar.share.props.visible = False self.edit_toolbar = EditToolbar() toolbox.add_toolbar(_('Edit'), self.edit_toolbar) |