Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge 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)
commit3dd64e23f215a7388982cf8560d58d1fdb4ae4ed (patch)
tree96a0999dfd32cc85bc29c8aac60e176c8df0363c
parent1c910a6a53ee169e2792588049e2d1be7115a082 (diff)
drag/drop, trash icons, album interactions
-rw-r--r--dbphoto.py49
-rw-r--r--display.py142
-rw-r--r--photo_toolbar.py4
-rw-r--r--startup_images/XoPhoto.svg54
-rw-r--r--startup_images/trash_empty.pngbin0 -> 64751 bytes
-rw-r--r--startup_images/trash_full.pngbin0 -> 75031 bytes
-rw-r--r--xophotoactivity.py10
7 files changed, 195 insertions, 64 deletions
diff --git a/dbphoto.py b/dbphoto.py
index dc02b24..5221c33 100644
--- a/dbphoto.py
+++ b/dbphoto.py
@@ -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
diff --git a/display.py b/display.py
index 1d739c7..077d21c 100644
--- a/display.py
+++ b/display.py
@@ -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
new file mode 100644
index 0000000..0aefec7
--- /dev/null
+++ b/startup_images/trash_empty.png
Binary files differ
diff --git a/startup_images/trash_full.png b/startup_images/trash_full.png
new file mode 100644
index 0000000..41764e9
--- /dev/null
+++ b/startup_images/trash_full.png
Binary files differ
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)