From 28a1c97a501b9006ed2438ccf550b57808c9ef5d Mon Sep 17 00:00:00 2001 From: root Date: Mon, 15 Nov 2010 01:04:30 +0000 Subject: startup on build 852 made interactive, shutdown fixes --- diff --git a/activity/activity.info b/activity/activity.info index d0dfe14..e59af4c 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,7 +1,7 @@ [Activity] name = XoPhoto bundle_id = org.laptop.XoPhoto -activity_version = 9 +activity_version = 8 show_launcher = yes icon = XoPhoto class = xophotoactivity.XoPhotoActivity diff --git a/dbphoto.py b/dbphoto.py index 77f88e9..5e38c29 100644 --- a/dbphoto.py +++ b/dbphoto.py @@ -60,7 +60,7 @@ console_formatter = logging.Formatter('%(name)s %(levelname)s %(funcName)s: %(li #_logger.addHandler(console_handler) -class DbAccess(): +class DbAccess: con = None cursor = None def __init__(self,fn): @@ -97,6 +97,7 @@ class DbAccess(): cursor.execute('select * from config') not_open = False except: + _logger.exception('sql "select * from config" failed.') not_open = True if not self.con or not_open: self.opendb(self.dbfilename) @@ -128,6 +129,10 @@ class DbAccess(): if self.con:self.con.close() self.con = None + def restart_db(self): + self.closedb() + self.opendb(self.dbfilename) + def get_mime_list(self): mime_list =[] conn = self.connection() @@ -165,7 +170,7 @@ class DbAccess(): #sql = """select groups.*, data_cache.picture.* from groups left join data_cache.picture \ #where groups.category = ? and groups.jobject_id = data_cache.picture.jobject_id order by groups.seq """ sql = """select groups.*, picture.* from groups, picture where category = ? - and groups.jobject_id = picture.jobject_id order by groups.seq""" + and groups.jobject_id = picture.jobject_id order by seq""" cursor = self.connection().cursor() cursor.execute(sql,(str(album_id),)) return cursor.fetchall() @@ -361,7 +366,14 @@ class DbAccess(): second parameter retured is row number for update/insert """ cursor = self.connection().cursor() - cursor.execute("select * from config where name = 'last_album'") + """ + try: + cursor.execute("select * from config where name = ?",('last_album',)) + except: + return None,0 + """ + cursor.execute("select * from config where name = ?",('last_album',)) + rows = cursor.fetchmany() _logger.debug('found %s last albums'%len(rows)) if len(rows) == 1: @@ -413,9 +425,7 @@ class DbAccess(): return None - def create_update_album(self,album_id,name,seq=None): - if not seq: - seq = 30 + def create_update_album(self,album_id,name): conn = self.connection() cursor = conn.cursor() cursor.execute('select * from groups where category = ? and subcategory = ?',\ @@ -428,7 +438,7 @@ class DbAccess(): (str(album_id),name,id)) else: cursor.execute("insert into groups (category,subcategory,stack_name,seq) values (?,?,?,?)",\ - ('albums',str(album_id),name,seq)) + ('albums',str(album_id),name,30)) conn.commit() if len(rows)>0: return diff --git a/display.py b/display.py index b486c1b..1ea4a02 100644 --- a/display.py +++ b/display.py @@ -438,7 +438,7 @@ class OneAlbum(): pass else: self._parent.paint_albums() - self.paint(True) + self.repaint() def release_cycles(self): while gtk.events_pending(): @@ -726,9 +726,13 @@ class OneAlbum(): class DisplayAlbums(): """Shows the photo albums on left side of main screen, responds to clicks, drag/drop events""" - predefined_albums = [(trash_id,_('Trash')),(journal_id,_('All Pictures')),] #_('Duplicates'),_('Last Year'),_('Last Month'),] + journal_id = '20100521T10:42' + trash_id = '20100521T11:40' + predefined_albums = [(journal_id,_('All Pictures')),(trash_id,_('Trash')),] #_('Duplicates'),_('Last Year'),_('Last Month'),] def __init__(self,db,activity): + db.restart_db() self.db = db #pointer to the open database + self._activity = activity #pointer to the top level activity self.album_sb = None @@ -754,14 +758,21 @@ class DisplayAlbums(): self.album_surface = pygame.Surface((album_column_width,screen_h)).convert() self.album_surface.fill(background_color) - #check for the required predefined albums - rows = self.db.get_albums() - timestamp_list = [] - for row in rows: - timestamp_list.append(row['subcategory']) - for album_tup in self.predefined_albums: - if album_tup[0] not in timestamp_list: - self.db.create_update_album(album_tup[0],album_tup[1],-1) + #if the albums table is empty, populate it from the journal, and initialize + sql = "select * from groups where category = 'albums'" + try: + rows,cur = self.db.dbdo(sql) + except: + rows = [] + i = 0 + if len(rows) == 0: #it is not initialized + #first put the predefined names in the list of albums + for album_tup in self.predefined_albums: + sql = """insert into groups (category,subcategory,stack_name,seq) \ + values ('%s','%s','%s',%s)"""%('albums',album_tup[0],album_tup[1],i,) + self.db.dbtry(sql) + i += 20 + self.db.commit() #initialize the list of album objects from the database album_rows = self.db.get_albums() @@ -785,8 +796,8 @@ class DisplayAlbums(): else: _logger.debug('display_thumbnails did not find %s'%album_id) - def display_journal(self): - self.display_thumbnails(journal_id) + def display_journal(self, new_surface = False): + self.display_thumbnails(self.journal_id, new_surface) def clear_albums(self): global album_background_color @@ -890,15 +901,15 @@ class DisplayAlbums(): self._activity.activity_toolbar.empty_journal_button.hide() if album_timestamp == trash_id: self._activity.activity_toolbar.empty_journal_button.show() - self._activity.activity_toolbar.set_label(display.menu_journal_label,False) + self._activity.activity_toolbar.set_label(display.menu_journal_label, False) elif album_timestamp == journal_id: - self._activity.activity_toolbar.set_label(display.menu_journal_label,True) + self._activity.activity_toolbar.set_label(display.menu_journal_label, True) self._activity.activity_toolbar.title.set_text(self._activity.metadata.get('title')) else: - self._activity.activity_toolbar.set_label(display.menu_stack_label,True) + self._activity.activity_toolbar.set_label(display.menu_stack_label, True) self._activity.activity_toolbar.title.set_text(album_title) - self.display_thumbnails(album_timestamp,new_surface=True) + self.display_thumbnails(album_timestamp, new_surface = True) pygame.display.flip() def add_to_current_album(self,jobject_id,current_album_id=None,name=None): @@ -1128,7 +1139,6 @@ class DisplayAlbums(): _logger.debug('calling update_resequendce with params %s,%s start_index:%s drop_index: %s drop_seq:%s new_seq:%s'% (groups_rec_id,new_seq,start_index,drop_index,drop_seq,new_seq,)) self.db.update_resequence(groups_rec_id,new_seq) - self.album_objects[self.selected_album_id].thumb_index = drop_index self.album_objects[self.selected_album_id].paint(True) def drag_album_onto_album(self,start_x,start_y,drop_x,drop_y): @@ -1338,13 +1348,12 @@ class Application(): db = None def __init__(self, activity): self._activity = activity - #self._activity.window.connect('activate-focus',self.expose_event_cb) self.file_tree = None self.util = Utilities(self._activity) self.album_collection = None self.vs = ViewSlides(self) - def first_run_setup(self): + def first_run_setup(self, alert, response): #scan the datastore and add new images as required source = os.path.join(os.environ['SUGAR_BUNDLE_PATH'],'startup_images') self.file_tree = FileTree(self.db,self._activity) @@ -1354,14 +1363,14 @@ class Application(): if number_of_pictures < 10: _logger.error('failed to initalize the datastore with at least 10 pictures') #exit(0) + else: + self.album_collection.display_journal(new_surface=True) + self.pygame_repaint() def change_album_name(self,name): if self.album_collection: self.album_collection.set_name(name) - def expose_event_cb(self,widget): - self.pygame_repaint() - def pygame_repaint(self): _logger.debug('pygame_repaint') if not self.album_collection: return @@ -1374,6 +1383,20 @@ class Application(): album_object.repaint_whole_screen() _logger.debug('pygame_repaint completed') return False + + def first_time_processing(self, images): + #fix for bug 2223 loads images repeatedly into journa--remember to only do once + start_images_loaded = self.db.get_lookup('image_init') + _logger.debug('config image_init:%s'%(start_images_loaded,)) + if not start_images_loaded == '': + return + #only ask the question the first time program is run + self.db.set_lookup('image_init','True') + if images < 10: + #ask if the user would like to have some images loaded into journal + title = _('THERE ARE ') + str(images) + _(' IMAGES ON YOUR XO and this activity works with images') + alert = self.util.confirmation_alert(_('Click OK to have a few practice pictures loaded into your XO'), + title, self.first_run_setup) def do_startup(self): start = time.clock() @@ -1392,7 +1415,7 @@ class Application(): #and 1 second when no records were added ds_count, added = self.ds_sql.check_for_recent_images() except PhotoException,e: - #This is a corrupted copy the sqlite database, start over + _logger.exception('This is a corrupted copy the sqlite database, start over') self.db.close() source = os.path.join(os.getcwd(),'xophoto.sqlite.template') dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite') @@ -1413,20 +1436,16 @@ class Application(): self.album_collection = DisplayAlbums(self.db, self._activity) self.album_collection.paint_albums() - - #if the picture table is empty, populate it from the journal, and initialize - #fix for bug 2223 loads images repeatedly into journal - start_images_loaded = self.db.get_lookup('image_init') - _logger.debug('config image_init:%s'%(start_images_loaded,)) - if ds_count < 10 and start_images_loaded == '': - self.db.set_lookup('image_init','True') - self.first_run_setup() - _logger.debug('took %s to do startup and paint albums'%(time.clock()-start)) - pygame.display.flip() + start = time.clock() - self.album_collection.display_journal() + #check for first time loading of a few images + self.first_time_processing(ds_count) + + self.album_collection.display_journal(new_surface = True) _logger.debug('took %s to display journal'%(time.clock()-start)) + pygame.display.flip() + def view_slides(self): album_object = self.set_album_for_viewslides() @@ -1437,8 +1456,6 @@ class Application(): self._activity.fullscreen() self.vs.show_title = True self.vs.next_slide() - #on return from viewing slides, restore the normal screen - #album_object.repaint_whole_screen() def set_album_for_viewslides(self): album_id = self.album_collection.selected_album_id @@ -1460,10 +1477,11 @@ class Application(): global startup_clock startup_clock = xophotoactivity.startup_clock if True: - if not self._activity.DbAccess_object: #we need to wait for the read-file to finish + if not self._activity.DbAccess_object: + #we need to wait for the read-file to finish Timer(5.0, self.end_db_delay, ()).start() in_db_wait = True - while not self._activity.DbAccess_object and in_db_wait: + while not (self._activity.DbAccess_object) and in_db_wait: gtk.main_iteration() if not self._activity.DbAccess_object: _logger.error('db object not open after timeout in Appplication.run') @@ -1490,13 +1508,10 @@ class Application(): _logger.debug('about to do_startup. Startup Clock:%f'%(time.clock()-startup_clock)) self.do_startup() - # Flip Display - pygame.display.flip() - - running = True + self.running = True x = 0 #initialize in case there is no mouse event _logger.debug('About to start running loop. Startup Clock:%f'%(time.clock()-startup_clock,)) - while running: + while self.running: #pygame.display.flip() # Pump GTK messages. while gtk.events_pending(): @@ -1506,15 +1521,18 @@ class Application(): if self.vs.running or self.vs.paused: self.vs.run() continue - # else fall through to do the main loop stuff. + + #during shutdown, the event.get will error + if not self.running: + continue for event in pygame.event.get(): if event.type in (MOUSEBUTTONDOWN,MOUSEBUTTONUP,MOUSEMOTION): x,y = event.pos if event.type == KEYUP: print event if event.key == K_ESCAPE: - #running = False + #self.running = False #pygame.quit() pass elif event.key == K_LEFT: @@ -1533,7 +1551,7 @@ class Application(): _logger.debug('restart database recognized') self._activity.read(none,initialize=True) self._activity.close() - running = False + self.running = False pygame.quit() #mouse events @@ -1693,6 +1711,10 @@ class Application(): if self.album_collection.selected_album_id == journal_id: return True return False + + def quit(self): + self.running = False + pygame.quit() class shim(): def __init__(self): diff --git a/photo_toolbar.py b/photo_toolbar.py index 94428f2..1ed1ece 100644 --- a/photo_toolbar.py +++ b/photo_toolbar.py @@ -186,7 +186,7 @@ class ActivityToolbar(gtk.Toolbar): self._activity.copy() def __stop_clicked_cb(self, button): - self._activity.close() + self._activity.stop() def __jobject_updated_cb(self, jobject): self.title.set_text(jobject['title']) diff --git a/sinks.py b/sinks.py index 945879e..ae5f651 100644 --- a/sinks.py +++ b/sinks.py @@ -288,10 +288,6 @@ class ViewSlides(): self.running = False self.paused = False #'gtk.STOCK_MEDIA_STOP' - if self.index == 0: - self.album_object.thumb_index = len(self.rows) - 1 - else: - self.album_object.thumb_index = self.index - 1 self.album_object.large_displayed = False self.album_object.repaint_whole_screen() diff --git a/xophotoactivity.py b/xophotoactivity.py index 05568b0..b4aa722 100644 --- a/xophotoactivity.py +++ b/xophotoactivity.py @@ -82,19 +82,14 @@ class XoPhotoActivity(activity.Activity): self._activity = self self.interactive_close = False self.timed_out = False - self.window_realized = False + self.realized = False self.game = None self.kept_once = False self.util = Utilities(self) self.db_sanity_checked = False gobject.GObject.__init__(self) self.jobject_id = None - - #there appears to be an initial save yourself, asynchronous, which - # in my write_file closes the database and causes sporatic failures - self.initial_save_yourself = False - - + 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) self.make_jobject = False @@ -105,7 +100,9 @@ class XoPhotoActivity(activity.Activity): if self.make_jobject: self.read_file(None) + self.interactive_close = True self.save() + self.interactive_close = False _logger.debug('At activity startup, handle.object_id is None. Making a new datastore entry') #does activity init execute the read? check if dbobject is reliably open @@ -120,6 +117,10 @@ class XoPhotoActivity(activity.Activity): self.toolbox.connect_after('current_toolbar_changed',self._toolbar_changed_cb) self.toolbox.show() """ + + #create a flag that indicates window realized + #self.connect_after('realize', self.realize_cb) + # Build the activity toolbar. self.build_toolbar() @@ -147,6 +148,12 @@ class XoPhotoActivity(activity.Activity): _logger.debug('Running the Game. Startup Clock:%f'%(time.clock()-startup_clock,)) self._pygamecanvas.run_pygame(self.game.run) + def pygame_repaint_cb(self,widget,event): + _logger.debug('pygame_repaint_cb. Realized:%s'%self.realized) + #if not self.realized: + # return + gobject.idle_add(self.game.pygame_repaint) + def build_toolbar(self): self.toolbox = photo_toolbar.ActivityToolbox(self) self.toolbox.connect_after('current_toolbar_changed',self._toolbar_changed_cb) @@ -206,10 +213,6 @@ class XoPhotoActivity(activity.Activity): self.toolbox.show() self.set_toolbox(self.toolbox) - def pygame_repaint_cb(self,widget,event): - _logger.debug('pygame_repaint_cb') - gobject.idle_add(self.game.pygame_repaint) - ################ Help routines def _toolbar_changed_cb(self,widget,tab_no): if tab_no == HELP_TAB: @@ -231,8 +234,9 @@ class XoPhotoActivity(activity.Activity): _logger.debug('xid for pydebug:%s'%self.pdb_window.xid) self.help_x11 = self.help.realize_help() else: - self.help.activate_help() - + self.help.activate_help() + ################ Help routines + def activity_toolbar_add_album_cb(self,album_name): self.game.album_collection.create_new_album(None) @@ -423,10 +427,17 @@ class XoPhotoActivity(activity.Activity): def use_toolbar_do_slideshow_stop_cb(self,use_toolbar): self.use_toolbar.set_running(False) self.game.vs.stop() + + def stop(self): + self.__stop_clicked_cb(None) def __stop_clicked_cb(self, button): + _logger.debug('entered the stop clicked call back') self.interactive_close = True + self.game.quit() self._activity.close() + #gtk.main_quit() + _logger.debug('completed the stop clicked call back') def non_conflicting(self,root,basename): """ @@ -575,13 +586,6 @@ class XoPhotoActivity(activity.Activity): _logger.debug('unable to rename:%s response:%s'%(cmd,rsp,)) self.DbAccess_object.closedb() dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite') - try: - self.DbAccess_object = DbAccess(dest) - if self.game: - self.game.db = self.DbAccess_object - except Exception,e: - _logger.debug('database failed to re-open after rewrite on data_cache file. error:%s'%e) - #exit() else: #need to start over with a new template and regenerate the thumbnails _logger.debug('swapping in template for transforms (thumbnail) database') @@ -593,11 +597,22 @@ class XoPhotoActivity(activity.Activity): except Exception,e: _logger.debug('data_cache template failed to copy error:%s'%e) exit() - + try: + self.DbAccess_object = DbAccess(dest) + if self.game: + self.game.db = self.DbAccess_object + except Exception,e: + _logger.exception('database failed to re-open after read routine. error:%s'%e) + exit() + + #last_album = self.DbAccess_object.get_last_album() _logger.debug('completed read_file. DbAccess_jobject is created. Since startup:%f'%(time.clock()-startup_clock,)) def write_file(self, file_path): - + """initially, I had write_file close/flush buffers. But the write_file appears to be in a different + thread, and it's asynchronous behavior causes db errors, if the database is closed in the middle of a + database operation. So we only close during an interactive close + """ try: if self.DbAccess_object and self.interactive_close: if self.DbAccess_object.get_error(): return #dont save a corrupted database @@ -626,19 +641,12 @@ class XoPhotoActivity(activity.Activity): try: #putting in an empty template makes it easier to make a distributable activity source = os.path.join(os.getcwd(),'xophoto.sqlite.template') shutil.copy(source,local_path) + _logger.debug('Normal XoPhoto Termination') except Exception,e: _logger.debug('database template failed to copy error:%s'%e) exit() else: #re-open the database - dest = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'],'data','xophoto.sqlite') - try: - self.DbAccess_object = DbAccess(dest) - if self.game: - self.game.db = self.DbAccess_object - except Exception,e: - _logger.debug('database failed to re-open in write file. error:%s'%e) - exit() - _logger.debug('sqlite datbase re-opened successfully') + _logger.debug('received a non-interactive write request. database left open') def unfullscreen(self): """this overrides the gtk.window function inherited by activity.Activity""" -- cgit v0.9.1