def delete_movie(self): m_id = None number, m_iter = self.get_maintree_selection() movie = self.db.Movie.get_by(number=number) if movie is None: gutils.error(self,_("You have no movies in your database"), self.widgets['window']) return False if int(movie.loaned)==1: gutils.warning(self, msg=_("You can't delete movie while it is loaned.")) return False response = gutils.question(self, _("Are you sure you want to delete this movie?"), \ 1, self.widgets['window']) if response == -8: # gtk.RESPONSE_YES == -8 # try to delete poster image as well if movie.image is not None: delete_poster(self, movie.image) if movie.remove_from_db(): # update main treelist self.total -= 1 self.treemodel.remove(m_iter) self.go_prev() self.clear_details() self.count_statusbar() else: return False
def convert_from_old_db(config, source_file, destination_file, locations): # {{{ """ convert .gri database into .bd one """ log.info("Converting old database - it can take several minutes...") log.debug("Source file: %s", source_file) gutils.info( _( "Griffith will now convert your database to the new format. This can take several minutes if you have a large database." ) ) from sql import GriffithSQL from gutils import digits_only import os if not os.path.isfile(source_file): return False if "home" not in locations: log.error("locations doesn't contain home path, cannot convert old database") return False if open(source_file).readline()[:47] == "** This file contains an SQLite 2.1 database **": log.debug("SQLite 2.1 detected") try: import sqlite except ImportError: log.error("Old DB conversion: please install pysqlite legacy (v1.0)") gutils.warning(_("Old DB conversion: please install pysqlite legacy (v1.0)")) return False else: try: # Python 2.5 from sqlite3 import dbapi2 as sqlite except ImportError: # Python < 2.5 - try to use pysqlite2 from pysqlite2 import dbapi2 as sqlite if os.path.isfile(destination_file): # rename destination_file if it already exist i = 1 while True: if os.path.isfile("%s_%s" % (destination_file, i)): i += 1 else: break os.rename(destination_file, "%s_%s" % (destination_file, i)) try: old_db = sqlite.connect(source_file) except sqlite.DatabaseError, e: if str(e) == "file is encrypted or is not a database": print "Your database is most probably in SQLite2 format, please convert it to SQLite3:" print "$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3" print "$ mv ~/.griffith/griffith.gri{,2}" print "$ mv ~/.griffith/griffith.gri{3,}" print "or install pysqlite in version 1.0" gutils.warning(_("Your database is most probably in SQLite2 format, please convert it to SQLite3")) else: raise return False
def __init__(self, config, griffith_dir, fallback=True): #mapper = Session.mapper self.config = config self.data_dir = griffith_dir if config.get('type', None, section='database') is None: config.set('type', 'sqlite', section='database') if config.get('type', 'sqlite', section='database') != 'sqlite': if config.get('host', None, section='database') is None: config.set('host', '127.0.0.1', section='database') if config.get('user', None, section='database') is None: config.set('user', 'griffith', section='database') if config.get('passwd', None, section='database') is None: config.set('passwd', 'gRiFiTh', section='database') if config.get('name', None, section='database') is None: config.set('name', 'griffith', section='database') if config.get('port', 0, section='database') == 0: config.set('port', GriffithSQL.DEFAULT_PORTS[config.get('type', section='database')], section='database') conn_params = config.to_dict(section='database') conn_params.update({'port': int(conn_params.get('port', 0)), 'engine_kwargs': {'echo': False, 'convert_unicode': False}}) # connect to database --------------------------------------{{{ if config.get('type', section='database') == 'sqlite': url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name']) elif config.get('type', section='database') == 'postgres': url = "postgres://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s" % conn_params elif config.get('type', section='database') == 'mysql': conn_params['engine_kwargs']['convert_unicode'] = True conn_params['engine_kwargs']['pool_recycle'] = int(config.get('pool_recycle', 3600, section='database')) url = "mysql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?charset=utf8&use_unicode=0" % conn_params elif config.get('type', section='database') == 'mssql': # use_scope_identity=0 have to be set as workaround for a sqlalchemy bug # but it is not guaranteed that the right identity value will be selected # because the select @@identity statement selects the very last id which # also can be a id from a trigger-insert or another user # sqlalchemy uses a wrong syntax. It has to select the id within the insert # statement: insert <table> (<columns>) values (<values>) select scope_identity() # (one statement !) After preparing and executing there should be a fetch # If it is executed as two separate statements the scope is lost after insert. url = "mssql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?use_scope_identity=0" % conn_params else: config.set('type', 'sqlite', section='database') url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name']) # try to establish a db connection try: engine = create_engine(url, **conn_params['engine_kwargs']) conn = engine.connect() except Exception, e: # InvalidRequestError, ImportError log.info("MetaData: %s", e) if not fallback: raise e config.set('type', 'sqlite', section='database') warning("%s\n\n%s" % (_('Cannot connect to database.\nFalling back to SQLite.'), _('Please check debug output for more informations.'))) url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name']) engine = create_engine(url) conn = engine.connect()
def delete_movie(self): m_id = None number, m_iter = self.get_maintree_selection() movie = self.db.session.query(db.Movie).filter_by(number=number).first() if movie is None: gutils.error(self,_("You have no movies in your database"), self.widgets['window']) return False if movie.loaned: gutils.warning(self, msg=_("You can't delete movie while it is loaned.")) return False response = gutils.question(_("Are you sure you want to delete this movie?"), True, self.widgets['window']) if response == -8: # gtk.RESPONSE_YES == -8 delete_poster(self, movie.poster_md5) self.db.session.delete(movie) try: self.db.session.commit() except: log.info("Unexpected problem: %s", e) return False # update main treelist self.total -= 1 self.clear_details() self.initialized = False self.go_prev() self.treemodel.remove(m_iter) self.initialized = True self.go_next() self.count_statusbar() else: return False
def save(gsql, widgets): """saves search conditions from current filter window""" cond = get_conditions(widgets) name = widgets['cb_name'].get_active_text().decode('utf-8') if not name: log.debug("search rule name is empty") info(_("Name is empty"), widgets['window']) return False session = gsql.Session() filter_ = session.query(db.Filter).filter_by(name=name).first() if filter_: filter_.data = cond isnew = False else: filter_ = db.Filter(name=name, data=cond) isnew = True session.add(filter_) try: session.commit() except Exception, e: session.rollback() log.warn(e) warning(_("Cannot save search conditions"), widgets['window']) return False
def delete_movie(self): if len(self.selected) == 0: gutils.error(_("You have no movies in your database"), self.widgets['window']) return False else: if gutils.question(_('Are you sure you want to delete?'), self.widgets['window']): for each in self.selected: movie = self.db.session.query( db.Movie).filter_by(number=int(each)).first() if movie.loaned: gutils.warning( msg=_("You can't delete movie while it is loaned.")) return False delete_poster(self, movie.poster_md5) self.db.session.delete(movie) try: self.db.session.commit() except: log.info("Unexpected problem: %s", e) return False # update main treelist self.total -= 1 self.clear_details() self.populate_treeview() #self.initialized = False #self.go_prev() #self.go_next() self.count_statusbar()
def delete_movie(self): if len(self.selected) == 0: gutils.error(_("You have no movies in your database"), self.widgets['window']) return False else: if gutils.question(_('Are you sure you want to delete?'), self.widgets['window']): for each in self.selected: movie = self.db.session.query(db.Movie).filter_by(number=int(each)).first() if movie.loaned: gutils.warning(msg=_("You can't delete movie while it is loaned.")) return False delete_poster(self, movie.poster_md5) self.db.session.delete(movie) try: self.db.session.commit() except: log.info("Unexpected problem: %s", e) return False # update main treelist self.total -= 1 self.clear_details() self.populate_treeview() #self.initialized = False #self.go_prev() #self.go_next() self.count_statusbar()
def commit(self): person_name = gutils.on_combo_box_entry_changed(self.widgets['movie']['loan_to']) if not person_name: return False self.widgets['w_loan_to'].hide() person = self.db.session.query(db.Person.person_id).filter_by(name=person_name).first() if not person: log.info("loan_commit: person doesn't exist") return False if self._movie_id: movie = self.db.session.query(db.Movie.movie_id, db.Movie.collection_id).filter_by(movie_id=self._movie_id).first() if not movie: log.info("loan_commit: wrong movie_id") return False else: log.info("loan_commit: movie not selected") return False # ask if user wants to loan whole collection loan_whole_collection = False if movie.collection_id > 0: response = gutils.question(_("Do you want to loan whole collection?"), window=self.widgets['window']) if response == gtk.RESPONSE_YES: loan_whole_collection = True elif response == gtk.RESPONSE_CANCEL: return False resp = sql.loan_movie(self.db, movie.movie_id, person.person_id, loan_whole_collection) if resp == -1: gutils.warning(_("Collection contains loaned movie.\nLoan aborted!")) return False elif resp: self.update_statusbar(_("Movie loaned")) self.treeview_clicked()
def delete(gsql, widgets): """deletes the current selected filter""" #hier muss was anderes her! nicht den text prüfen, da bei manchem anwender ein leereintrag existiert name = widgets['cb_name'].get_active_text().decode('utf-8') if not name: log.debug("search rule name is empty") info(_("Name is empty"), widgets['window']) return False session = gsql.Session() filter = session.query(db.Filter).filter_by(name=name).first() if filter: session.delete(filter) try: session.commit() except: session.rollback() log.exception('') warning(_("Cannot delete search conditions"), widgets['window']) return False else: widgets['cb_name'].remove_text(widgets['cb_name'].get_active()) info(_("Search conditions deleted"), widgets['window']) widgets['name'].set_text('')
def commit(session): try: session.commit() except IntegrityError, e: session.rollback() log.warn("Cannot commit movie: %s", e.message) gutils.warning(unicode(e.orig)) return False
def commit(self, session): try: session.commit() except IntegrityError, e: session.rollback() gutils.warning(self, str(e.orig)) log.warn("Cannot commit movie: %s", e.message) return False
def fetch_bigger_poster(self): match = 0 self.debug.show("fetching poster from amazon") movie = self.db.Movie.get_by(movie_id=self._movie_id) if movie is None: gutils.error(self,_("You have no movies in your database"), self.widgets['window']) return False current_poster = movie.image amazon.setLicense("04GDDMMXX8X9CJ1B22G2") locale = self.config.get('amazon_locale', 0, section='add') keyword = self.widgets['movie']['o_title'].get_text().decode('utf-8') if locale == '1': locale = 'uk' elif locale == '2': locale = 'de' keyword = self.widgets['movie']['title'].get_text().decode('utf-8') elif locale == '3': locale = 'ca' elif locale == '4': locale = 'fr' elif locale == '5': locale = 'jp' else: locale = None try: result = amazon.searchByKeyword(keyword, type="Large", product_line="DVD", locale=locale) self.debug.show("Posters found on amazon: %s posters" % result.TotalResults) except: gutils.warning(self, _("No posters found for this movie.")) return from widgets import connect_poster_signals, reconnect_add_signals connect_poster_signals(self, get_poster_select_dc, result, current_poster) if not len(result.Item): gutils.warning(self, _("No posters found for this movie.")) reconnect_add_signals(self) return for f in range(len(result.Item)): if self.widgets['movie']['o_title'].get_text().decode('utf-8') == result.Item[f].ItemAttributes.Title: get_poster(self, f, result, current_poster) return self.treemodel_results.clear() self.widgets['add']['b_get_from_web'].set_sensitive(False) # disable movie plugins (result window is shared) for f in range(len(result.Item)): if hasattr(result.Item[f], "LargeImage") and len(result.Item[f].LargeImage.URL): title = result.Item[f].ItemAttributes.Title myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(f)) self.treemodel_results.set_value(myiter, 1, title) self.widgets['results']['window'].show() self.widgets['results']['window'].set_keep_above(True)
def fetch_bigger_poster(self): match = 0 self.debug.show("fetching poster from amazon") movie = self.db.Movie.get_by(movie_id=self._movie_id) if movie is None: gutils.error(self, _("You have no movies in your database"), self.widgets["window"]) return False current_poster = movie.image amazon.setLicense("04GDDMMXX8X9CJ1B22G2") locale = self.config.get("amazon_locale", 0) if locale == 1: locale = "uk" elif locale == 2: locale = "de" elif locale == 3: locale = "uk" else: locale = None try: result = amazon.searchByKeyword( self.widgets["movie"]["o_title"].get_text(), type="lite", product_line="dvd", locale=locale ) self.debug.show("Posters found on amazon: %s posters" % len(result)) except: gutils.warning(self, _("No posters found for this movie.")) return from widgets import connect_poster_signals, reconnect_add_signals connect_poster_signals(self, get_poster_select_dc, result, current_poster) if not len(result): gutils.warning(self, _("No posters found for this movie.")) reconnect_add_signals(self) return for f in range(len(result)): if self.widgets["movie"]["o_title"].get_text() == result[f].ProductName: get_poster(self, f, result, current_poster) return self.treemodel_results.clear() self.widgets["add"]["b_get_from_web"].set_sensitive(False) # disable movie plugins (result window is shared) for f in range(len(result)): if len(result[f].ImageUrlLarge): title = result[f].ProductName myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(f)) self.treemodel_results.set_value(myiter, 1, title) self.widgets["results"]["window"].show() self.widgets["results"]["window"].set_keep_above(True)
def update_person(self): p = self.db.session.query(db.Person).filter_by(person_id=self.widgets['person']['e_id'].get_text().decode('utf-8')).first() if not p: log.warning('Person not found') return False try: p.name = self.widgets['person']['e_name'].get_text().decode('utf-8') p.email = self.widgets['person']['e_email'].get_text().decode('utf-8') p.phone = self.widgets['person']['e_phone'].get_text().decode('utf-8') except ValueError, e: gutils.warning(e.message) return False
def export_data(self, widget): """Main exporting function""" config = self.settings fields = self.fields tid = config["template"] # get data from widgets self.settings["export_dir"] = self.widgets["fcw"].get_filename() self.settings["title"] = self.widgets["entry_header"].get_text().decode("utf-8") self.settings["sorting"] = self.names[self.widgets["combo_sortby"].get_active_text().decode("utf-8")] if self.widgets["cb_reverse"].get_active(): self.settings["sorting2"] = "DESC" else: self.settings["sorting2"] = "ASC" self.settings["split_num"] = self.widgets["sb_split_num"].get_value_as_int() self.settings["poster_height"] = self.widgets["sb_height"].get_value_as_int() self.settings["poster_width"] = self.widgets["sb_width"].get_value_as_int() if self.widgets["cb_black"].get_active(): self.settings["poster_mode"] = "L" else: self.settings["poster_mode"] = "RGB" self.settings["poster_format"] = self.widgets["combo_format"].get_active_text() # persist config if self.config is not None: for name, value in config.items(): self.config.set(name, value, section="export-html") selected_fields = "" for name, value in self.fields.items(): if value: selected_fields = selected_fields + name + "," self.config.set("selected_fields", selected_fields, section="export-html") self.config.save() # create directories if not config["export_dir"]: log.info("Error: Folder name not set!") return 1 if not os.path.isdir(config["export_dir"]): try: os.mkdir(config["export_dir"]) except: gutils.error(_("Can't create %s!") % config["export_dir"]) return 2 data_path = os.path.join(self.locations["share"], "export_templates", self.templates[tid]["dir"], "data") if os.path.isdir(data_path): try: gutils.copytree(data_path, config["export_dir"]) except Exception, err: gutils.warning(str(err))
def export_data(self, widget): """Main exporting function""" config = self.settings fields = self.fields tid = config['template'] # get data from widgets self.settings['export_dir'] = self.widgets['fcw'].get_filename() self.settings['title'] = self.widgets['entry_header'].get_text().decode('utf-8') self.settings['sorting'] = self.names[self.widgets['combo_sortby'].get_active_text().decode('utf-8')] if self.widgets['cb_reverse'].get_active(): self.settings['sorting2'] = 'DESC' else: self.settings['sorting2'] = 'ASC' self.settings['split_num'] = self.widgets['sb_split_num'].get_value_as_int() self.settings['poster_height'] = self.widgets['sb_height'].get_value_as_int() self.settings['poster_width'] = self.widgets['sb_width'].get_value_as_int() if self.widgets['cb_black'].get_active(): self.settings['poster_mode'] = 'L' else: self.settings['poster_mode'] = 'RGB' self.settings['poster_format'] = self.widgets['combo_format'].get_active_text() # persist config if self.config is not None: for name, value in config.items(): self.config.set(name, value, section='export-html') selected_fields = '' for name, value in self.fields.items(): if value: selected_fields = selected_fields + name + ',' self.config.set('selected_fields', selected_fields, section='export-html') self.config.save() # create directories if not config['export_dir']: log.info("Error: Folder name not set!") return 1 if not os.path.isdir(config['export_dir']): try: os.mkdir(config['export_dir']) except: gutils.error(_("Can't create %s!") % config['export_dir']) return 2 data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data') if os.path.isdir(data_path): try: gutils.copytree(data_path, config['export_dir']) except Exception, err: gutils.warning(str(err))
def convert_from_old_db(self, source_file, destination_file): #{{{ print 'Converting old database - it can take several minutes...' gutils.info(self,_("Griffith will now convert your database to the new format. This can take several minutes if you have a large database.")) from sqlalchemy.orm import clear_mappers from sql import GriffithSQL from gutils import digits_only import os if not os.path.isfile(source_file): return False if open(source_file).readline()[:47] == '** This file contains an SQLite 2.1 database **': try: import sqlite from sqlite import DatabaseError except ImportError: print 'Old DB conversion: please install pysqlite legacy (v1.0)' gutils.warning(self,_("Old DB conversion: please install pysqlite legacy (v1.0)")) return False else: try: # Python 2.5 from sqlite3 import dbapi2 as sqlite from sqlite3.dbapi2 import DatabaseError except ImportError: # Python < 2.5 - try to use pysqlite2 from pysqlite2 import dbapi2 as sqlite from pysqlite2.dbapi2 import DatabaseError if os.path.isfile(destination_file): # rename destination_file if it already exist i = 1 while True: if os.path.isfile("%s_%s" % (destination_file, i)): i += 1 else: break os.rename(destination_file, "%s_%s" % (destination_file, i)) try: old_db = sqlite.connect(source_file) except DatabaseError, e: if str(e) == 'file is encrypted or is not a database': print 'Your database is most probably in wrong SQLite format, please convert it to SQLite3:' print '$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3' print '$ mv ~/.griffith/griffith.gri{,2}' print '$ mv ~/.griffith/griffith.gri{3,}' print 'or install pysqlite in version 1.0' gutils.warning(self,_("Your database is most probably in SQLite2 format, please convert it to SQLite3")) else: raise return False
def update_collection(self, id, name=None, volume_id=None, loaned=None): if str(id) == '0': self.debug.show("You have to select collection first") return False if name!=None: tmp = self.get_value(field="id", table="collections", where="name='%s'"%name) if tmp != None: self.debug.show("This name is already in use (id=%s)"%tmp) gutils.warning(self, msg="This name is already in use!") return False try: self.cursor.execute("UPDATE collections SET name = '%s' WHERE id = '%s';"%(name,id)) except: self.debug.show("ERROR during updating collection's name!") return False return True if loaned==1: try: self.cursor.execute(""" UPDATE collections SET loaned='1' WHERE id='%s'; UPDATE movies SET loaned='1' WHERE collection_id='%s'; """ % (id, id)) except: self.debug.show("ERROR during updating collection's loan data!") return False if volume_id: try: self.cursor.execute("UPDATE volumes SET loaned='1' WHERE id='%s';"%volume_id) except: self.debug.show("ERROR during updating volume's loan data!") return False return True elif loaned==0: try: self.cursor.execute(""" UPDATE collections SET loaned='0' WHERE id='%s'; UPDATE movies SET loaned='0' WHERE collection_id='%s'; """ %( id, id)) except: self.debug.show("ERROR during updating collection's loan data!") return False if volume_id: try: self.cursor.execute("UPDATE volumes SET loaned='0' WHERE id='%s';"%volume_id) except: self.debug.show("ERROR during updating volume's loan data!") return False return True return False
def update_language(self, id, name): if str(id) == '0': self.debug.show("You have to select language first") return False tmp = self.get_value(field="id", table="languages", where="name='%s'"%name) if tmp != None: self.debug.show("This name is already in use (id=%s)"%tmp) gutils.warning(self, msg="This name is already in use!") return False try: self.cursor.execute("UPDATE languages SET name ='%s' WHERE id='%s';" % (name, id)) except: self.debug.show("ERROR during updating language name!") return False return True
def update_person(self): p = ( self.db.session.query(db.Person) .filter_by(person_id=self.widgets["person"]["e_id"].get_text().decode("utf-8")) .first() ) if not p: log.warning("Person not found") return False try: p.name = self.widgets["person"]["e_name"].get_text().decode("utf-8") p.email = self.widgets["person"]["e_email"].get_text().decode("utf-8") p.phone = self.widgets["person"]["e_phone"].get_text().decode("utf-8") except ValueError, e: gutils.warning(e.message) return False
def add_person_db(self): name = self.widgets['person']['name'].get_text().decode('utf-8') if name: p = db.Person() try: p.name = self.widgets['person']['name'].get_text().decode('utf-8') p.email = self.widgets['person']['email'].get_text().decode('utf-8') p.phone = gutils.digits_only(self.widgets['person']['phone'].get_text().decode('utf-8')) except ValueError, e: gutils.warning(e.message) return False self.widgets['person']['window'].hide() self.db.session.add(p) try: self.db.session.commit() except Exception, e: log.info(str(e))
def delete_movie(self): m_id = None m_id, m_iter = self.get_maintree_selection() if self.db.is_movie_loaned(movie_number=m_id): gutils.warning(self, msg=_("You can't delete movie while it is loaned.")) return False response = gutils.question(self,_("Are you sure you want to delete this movie?"), \ 1, self.main_window) if response == -8: # gtk.RESPONSE_YES == -8 # try to delete poster image as well poster = self.db.get_value('image', table="movies", where="number='%s'"%m_id) if poster != None: delete_poster(self, poster) delete_movie_from_db(self, m_id, m_iter) self.main_treeview.set_cursor_on_cell(self.total_filter-1) else: return False
def add_person_db(self): name = self.widgets['person']['name'].get_text().decode('utf-8') if name: p = db.Person() try: p.name = self.widgets['person']['name'].get_text().decode('utf-8') p.email = self.widgets['person']['email'].get_text().decode('utf-8') p.phone = gutils.digits_only(self.widgets['person']['phone'].get_text().decode('utf-8')) except ValueError, e: gutils.warning(e.message) return False self.widgets['person']['window'].hide() self.db.session.add(p) try: self.db.session.commit() except Exception, e: self.db.session.rollback() log.info(str(e))
def update_tag(self, id, name): if id == None: self.debug.show("You have to select tag first") return False if name == '': self.debug.show("Tag's name is empty") return False tmp = self.get_value(field="id", table="tags", where="name='%s'"%name) if tmp != None: self.debug.show("This name is already in use (id=%s)"%tmp) gutils.warning(self, msg="This name is already in use!") return False try: self.cursor.execute("UPDATE tags SET name ='%s' WHERE id='%s';" % (name,id)) except: self.debug.show("ERROR during updating tag name!") return False return True
def add_person_db(self): name = self.widgets["person"]["name"].get_text().decode("utf-8") if name: p = db.Person() try: p.name = self.widgets["person"]["name"].get_text().decode("utf-8") p.email = self.widgets["person"]["email"].get_text().decode("utf-8") p.phone = gutils.digits_only(self.widgets["person"]["phone"].get_text().decode("utf-8")) except ValueError, e: gutils.warning(e.message) return False self.widgets["person"]["window"].hide() self.db.session.add(p) try: self.db.session.commit() except Exception, e: self.db.session.rollback() log.info(str(e))
def export_data(self, widget): """Main exporting function""" config = self.config fields = self.fields tid = config["template"] # get data from widgets self.config["exported_dir"] = self.widgets["fcw"].get_filename() self.config["title"] = self.widgets["entry_header"].get_text() self.config["sorting"] = self.names[self.widgets["combo_sortby"].get_active_text()] if self.widgets["cb_reverse"].get_active(): self.config["sorting2"] = "DESC" else: self.config["sorting2"] = "ASC" self.config["split_num"] = self.widgets["sb_split_num"].get_value_as_int() self.config["poster_height"] = self.widgets["sb_height"].get_value_as_int() self.config["poster_width"] = self.widgets["sb_width"].get_value_as_int() if self.widgets["cb_black"].get_active(): self.config["poster_mode"] = "L" else: self.config["poster_mode"] = "RGB" self.config["poster_format"] = self.widgets["combo_format"].get_active_text() # create directories if not config["exported_dir"]: self.debug.show("Error: Folder name not set!") return 1 if not os.path.isdir(config["exported_dir"]): try: os.mkdir(config["exported_dir"]) except: gutils.error(self, _("Can't create %s!") % config["exported_dir"]) return 2 data_path = os.path.join(self.locations["share"], "export_templates", self.templates[tid]["dir"], "data") if os.path.isdir(data_path): try: gutils.copytree(data_path, config["exported_dir"]) except Exception, err: gutils.warning(self, str(err))
def commit(self): person_name = gutils.on_combo_box_entry_changed( self.widgets['movie']['loan_to']) if not person_name: return False self.widgets['w_loan_to'].hide() session = self.db.Session() person = session.query( db.Person.person_id).filter_by(name=person_name).first() if not person: log.warn("loan_commit: person doesn't exist") return False if self._movie_id: movie = session.query( db.Movie).filter_by(movie_id=self._movie_id).first() if not movie: log.warn("loan_commit: movie doesn't exist") return False else: log.warn("loan_commit: movie not selected") return False # ask if user wants to loan whole collection loan_whole_collection = False if movie.collection_id > 0: if gutils.question(_('Do you want to loan the whole collection?'), window=self.widgets['window']): loan_whole_collection = True try: if movie.loan_to(person, whole_collection=loan_whole_collection): session.commit() except Exception, e: session.rollback() if e.message == 'loaned movies in the collection already': gutils.warning( _("Collection contains loaned movie.\nLoan aborted!")) return False else: raise e
def export_data(self, widget): """Main exporting function""" config = self.config fields = self.fields tid = config['template'] # get data from widgets self.config['exported_dir'] = self.widgets['fcw'].get_filename() self.config['title'] = self.widgets['entry_header'].get_text() self.config['sorting'] = self.names[self.widgets['combo_sortby'].get_active_text()] if self.widgets['cb_reverse'].get_active(): self.config['sorting2'] = 'DESC' else: self.config['sorting2'] = 'ASC' self.config['split_num'] = self.widgets['sb_split_num'].get_value_as_int() self.config['poster_height'] = self.widgets['sb_height'].get_value_as_int() self.config['poster_width'] = self.widgets['sb_width'].get_value_as_int() if self.widgets['cb_black'].get_active(): self.config['poster_mode'] = 'L' else: self.config['poster_mode'] = 'RGB' self.config['poster_format'] = self.widgets['combo_format'].get_active_text() # create directories if not config['exported_dir']: self.debug.show("Error: Folder name not set!") return 1 if not os.path.isdir(config['exported_dir']): try: os.mkdir(config['exported_dir']) except: gutils.error(self,_("Can't create %s!") % config['exported_dir']) return 2 data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data') if os.path.isdir(data_path): try: gutils.copytree(data_path, config['exported_dir']) except Exception, err: gutils.warning(self, str(err))
def remove_collection(self, id=None, name=None): if id != None: name = self.get_value(field="name", table="collections", where="id = '%s'" % id) elif name != None and name != '' and id == None: name = gutils.gescape(name) id = self.get_value(field="id", table="collections", where="name = '%s'" % name) id = str(int(id)) if str(id) == '0' or id == None: self.debug.show("You have to select collection first") return False movies = int(self.get_value(field="count(id)", table="movies", where="collection_id = '%s'" % id)) if movies > 0: gutils.warning(self, msg="%s movie(s) in this collection.\nRemoval is possible only if there is no movie assigned to collection"%str(movies)) return False self.debug.show("Removing '%s' collection (id=%s) from database..."%(name, id)) try: self.cursor.execute("DELETE FROM collections WHERE id = '%s'" % id) except: return False return True
def commit(self): person_name = gutils.on_combo_box_entry_changed(self.widgets['movie']['loan_to']) if not person_name: return False self.widgets['w_loan_to'].hide() session = self.db.Session() person = session.query(db.Person.person_id).filter_by(name=person_name).first() if not person: log.warn("loan_commit: person doesn't exist") return False if self._movie_id: movie = session.query(db.Movie).filter_by(movie_id=self._movie_id).first() if not movie: log.warn("loan_commit: movie doesn't exist") return False else: log.warn("loan_commit: movie not selected") return False # ask if user wants to loan whole collection loan_whole_collection = False if movie.collection_id > 0: response = gutils.question(_("Do you want to loan whole collection?"), window=self.widgets['window']) if response == gtk.RESPONSE_YES: loan_whole_collection = True elif response == gtk.RESPONSE_CANCEL: return False try: if movie.loan_to(person, whole_collection=loan_whole_collection): session.commit() except Exception, e: session.rollback() if e.message == 'loaned movies in the collection already': gutils.warning(_("Collection contains loaned movie.\nLoan aborted!")) return False else: raise e
def remove_tag(self, id=None, name=None): if id != None: name = self.get_value(field="name", table="tags", where="id = '%s'"%id) elif name != None and name != '' and id == None: name = gutils.gescape(name) id = self.get_value(field="id", table="tags", where="name = '%s'"%name) id = str(int(id)) if str(id) == '0' or id == None: self.debug.show("You have to select tag first") return False movies = int(self.get_value(field="count(movie_id)", table="movie_tag", where="tag_id = '%s'" % id)) if movies > 0: gutils.warning(self, msg="%s movie(s) are assigned to this tag.\nChange movie details first!"%str(movies)) return False self.debug.show("Removing '%s' tag (id=%s) from database..."%(name, id)) try: self.cursor.execute("DELETE FROM tags WHERE id = '%s'" % id) except: return False return True
def fetch_bigger_poster(self): match = 0 self.debug.show("fetching poster from amazon") this_movie = self.db.select_movie_by_num(self.e_number.get_text()) current_poster = this_movie[0]['image'] amazon.setLicense("04GDDMMXX8X9CJ1B22G2") try: result = amazon.searchByKeyword(self.e_original_title.get_text(), \ type="lite", product_line="dvd") self.debug.show("Posters found on amazon: %s posters" % len(result)) except: gutils.warning(self, _("No posters found for this movie.")) return widgets.connect_poster_signals(self, get_poster_select_dc, result, current_poster) if not len(result): gutils.warning(self, _("No posters found for this movie.")) return for f in range(len(result)): if self.e_original_title.get_text() == result[f].ProductName: get_poster(self, f, result, current_poster) return self.treemodel_results.clear() for f in range(len(result)): if (len(result[f].ImageUrlLarge)): title = result[f].ProductName self.debug.show(title) myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(f)) self.treemodel_results.set_value(myiter, 1, title) self.w_results.show() self.w_results.set_keep_above(True)
def convert_from_old_db(self, source_file, destination_file): #{{{ # TODO: table.insert().execute({'number':1, 'o_title':'test1'}, {'number':2, 'title: 'test2'}) is faster! print 'Converting old database - it can take several minutes...' gutils.info(self,_("Griffith will now convert your database to the new format. This can take several minutes if you have a large database.")) from sqlalchemy.orm import clear_mappers from sql import GriffithSQL from gutils import digits_only import os try: import sqlite from sqlite import DatabaseError except: print 'Old DB conversion: please install pysqlite legacy (v1.0)' gutils.warning(self,_("Old DB conversion: please install pysqlite legacy (v1.0)")) return False if os.path.isfile(destination_file): # rename destination_file if it already exist i = 1 while True: if os.path.isfile("%s_%s" % (destination_file, i)): i += 1 else: break os.rename(destination_file, "%s_%s" % (destination_file, i)) try: old_db = sqlite.connect(source_file,autocommit=0) except DatabaseError, e: if str(e) == 'file is encrypted or is not a database': print 'Your database is most probably in SQLite3 format, please convert it to SQLite2:' print '$ sqlite3 ~/.griffith/griffith.gri .dump | sqlite ~/.griffith/griffith.gri2' print '$ mv ~/.griffith/griffith.gri{,3}' print '$ mv ~/.griffith/griffith.gri{2,}' print 'or install pysqlite in version 1.1' gutils.warning(self,_("Your database is most probably in SQLite3 format, please convert it to SQLite2")) else: raise return False
def delete(gsql, widgets): """deletes the current selected filter""" name = widgets['cb_name'].get_active_text().decode('utf-8') if not name: log.debug("search rule name is empty") info(_("Name is empty"), widgets['window']) return False session = gsql.Session() filter = session.query(db.Filter).filter_by(name=name).first() if filter: session.delete(filter) try: session.commit() except: session.rollback() log.exception('') warning(_("Cannot delete search conditions"), widgets['window']) return False else: widgets['cb_name'].remove_text(widgets['cb_name'].get_active()) info(_("Search conditions deleted"), widgets['window']) widgets['name'].set_text('')
def convert_from_old_db(config, source_file, destination_file, locations): #{{{ """ convert .gri database into .bd one """ log.info('Converting old database - it can take several minutes...') log.debug("Source file: %s", source_file) gutils.info( _("Griffith will now convert your database to the new format. This can take several minutes if you have a large database." )) from sql import GriffithSQL from gutils import digits_only import os if not os.path.isfile(source_file): return False if 'home' not in locations: log.error( "locations doesn't contain home path, cannot convert old database") return False if open(source_file).readline( )[:47] == '** This file contains an SQLite 2.1 database **': log.debug('SQLite 2.1 detected') try: import sqlite except ImportError: log.error( 'Old DB conversion: please install pysqlite legacy (v1.0)') gutils.warning( _("Old DB conversion: please install pysqlite legacy (v1.0)")) return False else: try: # Python 2.5 from sqlite3 import dbapi2 as sqlite except ImportError: # Python < 2.5 - try to use pysqlite2 from pysqlite2 import dbapi2 as sqlite if os.path.isfile(destination_file): # rename destination_file if it already exist i = 1 while True: if os.path.isfile("%s_%s" % (destination_file, i)): i += 1 else: break os.rename(destination_file, "%s_%s" % (destination_file, i)) try: old_db = sqlite.connect(source_file) except sqlite.DatabaseError, e: if str(e) == 'file is encrypted or is not a database': print 'Your database is most probably in SQLite2 format, please convert it to SQLite3:' print '$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3' print '$ mv ~/.griffith/griffith.gri{,2}' print '$ mv ~/.griffith/griffith.gri{3,}' print 'or install pysqlite in version 1.0' gutils.warning( _("Your database is most probably in SQLite2 format, please convert it to SQLite3" )) else: raise return False
class ExportPlugin(Base): name = 'HTML' description = _('Plugin exports data using templates') author = 'Piotr Ożarowski' email = '*****@*****.**' version = '4.0' #==[ configuration - default values ]==========={{{ settings = { 'sorting': 'movies_title', 'sorting2': 'ASC', 'export_dir': '', 'template': 2, 'title': _("Griffith's movies list"), 'style': 0, 'custom_style': False, 'custom_style_file': None, 'split_num': 50, # split into x files/pages 'split_by': 1, # 0==files, 1==movies 'poster_convert': False, # dont convert 'poster_height': 200, 'poster_width': 150, 'poster_mode': 'RGB', # RGB == color, L == black and white 'poster_format': 'jpeg' } fields = { 'movies_cast': False, 'movies_classification': False, 'movies_country': True, 'movies_genre': True, 'movies_director': True, 'movies_image': True, 'movies_o_site': True, 'movies_site': True, 'movies_trailer': True, 'movies_loaned': False, 'movies_media_num': True, 'movies_number': True, 'movies_o_title': True, 'movies_plot': False, 'movies_rating': True, 'movies_runtime': True, 'movies_studio': False, 'movies_seen': True, 'movies_title': True, 'movies_year': True, 'movies_notes': False, 'movies_screenplay': False, 'movies_cameraman': False, 'movies_width': False, 'movies_height': False, 'movies_barcode': False, # 'movies_region' : False, # 'movies_layers' : False, # 'movies_condition' : False, # 'movies_color' : False, # 'movies_volume_id' : False, # 'movies_collection_id' : False, 'media_name': True, 'collections_name': True, 'volumes_name': True, # 'acodecs_name' : True, 'vcodecs_name': True, } fields_as_columns = { 'movies_cast': 'cast', 'movies_classification': 'classification', 'movies_country': 'country', 'movies_genre': 'genre', 'movies_director': 'director', 'movies_image': 'poster_md5', 'movies_o_site': 'o_site', 'movies_site': 'site', 'movies_trailer': 'trailer', 'movies_loaned': 'loaned', 'movies_media_num': 'media_num', 'movies_number': 'number', 'movies_o_title': 'o_title', 'movies_plot': 'plot', 'movies_rating': 'rating', 'movies_runtime': 'runtime', 'movies_studio': 'studio', 'movies_seen': 'seen', 'movies_title': 'title', 'movies_year': 'year', 'movies_notes': 'notes', 'movies_screenplay': 'screenplay', 'movies_cameraman': 'cameraman', 'movies_width': 'width', 'movies_height': 'height', 'movies_barcode': 'barcode', # 'movies_region' : 'region', # 'movies_layers' : 'layers', # 'movies_condition' : 'condition', # 'movies_color' : 'color', # 'movies_volume_id' : 'volume_id', # 'movies_collection_id' : 'collection_id', 'media_name': 'name', 'collections_name': 'name', 'volumes_name': 'name', # 'acodecs_name' : 'name', 'vcodecs_name': 'name', } names = { _('Cast'): 'movies_cast', _('Classification'): 'movies_classification', _('Country'): 'movies_country', _('Director'): 'movies_director', _('Genre'): 'movies_genre', _('Image'): 'movies_image', _('Official site'): 'movies_o_site', _('Site'): 'movies_site', _('Trailer'): 'movies_trailer', _('Loaned'): 'movies_loaned', _('Discs'): 'movies_media_num', _('Number'): 'movies_number', _('Original Title'): 'movies_o_title', _('Plot'): 'movies_plot', _('Rating'): 'movies_rating', _('Runtime'): 'movies_runtime', _('Studio'): 'movies_studio', _('Seen it'): 'movies_seen', _('Title'): 'movies_title', _('Year'): 'movies_year', _('Notes'): 'movies_notes', _('Screenplay'): 'movies_screenplay', _('Cameraman'): 'movies_cameraman', _('Width'): 'movies_width', _('Height'): 'movies_height', _('Barcode'): 'movies_barcode', # _('Region') : 'movies_region', # _('Layers') : 'movies_layers', # _('Condition') : 'movies_condition', # _('Color') : 'movies_color', # _('Volume') : 'movies_volume_id', # _('Collection') : 'movies_collection_id', _('Media'): 'media_name', _('Collection'): 'collections_name', _('Volume'): 'volumes_name', # _('Audio codecs') : 'acodecs_name', _('Video codec'): 'vcodecs_name', } #}}} def initialize(self): #{{{ self.fields_to_export = [] for field in ExportPlugin.fields: if field == 'movies_image': self.fields_to_export.append('movies.poster_md5') else: pos = field.find('_') self.fields_to_export.append("%s.%s" % (field[:pos], field[pos + 1:])) self.widgets = {} self.style_list = {} self.templates = self.make_template_list() # glade gf = os.path.join(self.locations['glade'], 'exporthtml.glade') self.load_configuration() self.define_widgets(gtk.glade.XML(gf)) self.fill_widgets() return True #}}} def load_configuration(self): #{{{ # persist config if self.config is not None: config = self.settings for name, value in config.items(): try: tmp = self.config.get(name, value, section='export-html') if isinstance(value, bool): config[name] = bool(int(tmp)) elif isinstance(value, int): config[name] = int(tmp) else: config[name] = tmp except: pass selected_fields = self.config.get('selected_fields', '', section='export-html') if selected_fields: for name in self.fields: self.fields[name] = False selected_fields = selected_fields.split(',') for selected_field in selected_fields: if selected_field in self.fields: self.fields[selected_field] = True #}}} def run(self): pass def get_node_value_by_language(self, parent, name, language='en'): #{{{ nodes = parent.getElementsByTagName(name) for node in nodes: if node.parentNode != parent: continue elif node.attributes.get('xml:lang') is not None: if node.attributes.get('xml:lang').value == language: return node.firstChild.nodeValue else: # set default value in case node has no xml:lang attribute value = node.firstChild.nodeValue return value #}}} def make_template_list(self): #{{{ language = 'en' if os.environ.has_key('LANG'): language = os.environ['LANG'][:2] templates = {} j = 0 # number of templates dirName = os.path.join(self.locations['share'], 'export_templates') items = os.listdir(dirName) items.sort() for i in items: fileName = os.path.join(dirName, i) if not os.path.islink(fileName) and os.path.isdir(fileName): # clear previous data doc = None styles = {} tpl_name = None tpl_author = None tpl_email = None tpl_version = None tpl_ext = None tpl_desc = None try: doc = minidom.parse(os.path.join(fileName, 'config.xml')) except: log.info( "Can't parse configuration file for template: %s" % fileName) continue for template in doc.getElementsByTagName('template'): tpl_name = self.get_node_value_by_language( template, 'name', language) tpl_author = template.getElementsByTagName( 'author')[0].firstChild.nodeValue tpl_email = template.getElementsByTagName( 'email')[0].firstChild.nodeValue tpl_version = template.getElementsByTagName( 'version')[0].firstChild.nodeValue tpl_ext = template.getElementsByTagName( 'extension')[0].firstChild.nodeValue tpl_desc = self.get_node_value_by_language( template, 'description', language) k = 0 # number of styles try: styles_list = template.getElementsByTagName( 'styles')[0].getElementsByTagName('style') for style in styles_list: tpl_style_name = self.get_node_value_by_language( style, 'name', language) tpl_style_file = style.getElementsByTagName( 'file')[0].firstChild.nodeValue # get preview if available try: tpl_style_preview = style.getElementsByTagName( 'preview')[0].firstChild.nodeValue except: tpl_style_preview = None styles[k] = { 'name': tpl_style_name, 'file': tpl_style_file, 'preview': tpl_style_preview } k = k + 1 except: styles = None if tpl_name == '': continue templates[j] = { 'dir': i, 'name': tpl_name, 'author': tpl_author, 'email': tpl_email, 'version': tpl_version, 'ext': tpl_ext, 'desc': tpl_desc, 'styles': styles } j = j + 1 return templates #}}} #==[ widgets ]=================================={{{ def define_widgets(self, glade_file): get = lambda x: glade_file.get_widget(x) self.widgets = { 'window': get('w_eh'), 'fcw': get('fcw'), 'box_include_1': get('box_include_1'), 'box_include_2': get('box_include_2'), 'box_include_3': get('box_include_3'), 'sb_split_num': get('sb_split_num'), 'rb_split_files': get('rb_split_files'), 'rb_split_movies': get('rb_split_movies'), 'entry_header': get('entry_header'), 'cb_custom_style': get('cb_custom_style'), 'cb_reverse': get('cb_reverse'), 'combo_style': get('combo_style'), 'combo_sortby': get('combo_sortby'), 'combo_theme': get('combo_theme'), 'fcb_custom_style_file': get('fcb_custom_style_file'), 'l_tpl_author': get('l_tpl_author'), 'l_tpl_email': get('l_tpl_email'), 'l_tpl_version': get('l_tpl_version'), 'l_tpl_desc': get('l_tpl_desc'), 'image_preview': get('image_preview'), 'vb_posters': get('vb_posters'), 'sb_height': get('sb_height'), 'sb_width': get('sb_width'), 'cb_black': get('cb_black'), 'combo_format': get('combo_format'), 'cb_convert': get('cb_convert'), } # define handlers for general events glade_file.signal_autoconnect({ 'on_export_button_clicked': self.export_data, 'on_rb_split_files_toggled': self.on_rb_split_files_toggled, 'on_rb_split_movies_toggled': self.on_rb_split_movies_toggled, 'on_cancel_button_clicked': self.on_quit, 'on_cb_data_toggled': self.on_cb_data_toggled, 'on_cb_custom_style_toggled': self.on_cb_custom_style_toggled, 'on_fcb_custom_style_file_activated': self.on_fcb_custom_style_file_activated, 'on_combo_style_changed': self.on_combo_style_changed, 'on_combo_theme_changed': self.on_combo_theme_changed, 'on_cb_convert_toggled': self.on_cb_convert_toggled, }) def fill_widgets(self): # themes for i in self.templates: self.widgets['combo_theme'].insert_text(i, self.templates[i]['name']) # sortby combo keys = self.names.keys() keys.sort() j = 0 pos_o_title = 0 for i in keys: self.widgets['combo_sortby'].append_text(i) if self.names[i] == self.settings['sorting']: pos_o_title = j j = j + 1 self.widgets['combo_sortby'].set_wrap_width(3) # include data j = 0 k = math.ceil(len(self.names) / float(3)) for i in keys: j = j + 1 field = self.names[i] self.widgets['cb_' + field] = gtk.CheckButton(i) self.widgets['cb_' + field].set_name("cb_%s" % field) self.widgets['cb_' + field].connect('toggled', self.on_cb_data_toggled) self.widgets['cb_' + field].set_active(self.fields[field]) if j <= k: self.widgets['box_include_1'].add(self.widgets["cb_%s" % field]) elif j <= 2 * k: self.widgets['box_include_2'].add(self.widgets["cb_%s" % field]) else: self.widgets['box_include_3'].add(self.widgets["cb_%s" % field]) self.widgets['box_include_1'].show_all() self.widgets['box_include_2'].show_all() self.widgets['box_include_3'].show_all() # set defaults -------------------------------- self.widgets['entry_header'].set_text(self.settings['title']) self.widgets['combo_sortby'].set_active(pos_o_title) if self.settings['sorting2'] == 'DESC': self.widgets['cb_reverse'].set_active(True) else: self.widgets['cb_reverse'].set_active(False) # template and theme style = self.settings[ 'style'] # save it temporary because change of the template set it 0 self.widgets['combo_theme'].set_active(self.settings['template']) self.widgets['combo_style'].set_active(style) self.widgets['cb_custom_style'].set_active( self.settings['custom_style']) if self.settings['custom_style_file']: self.widgets['fcb_custom_style_file'].set_filename( self.settings['custom_style_file']) # spliting self.widgets['sb_split_num'].set_value(self.settings['split_num']) if self.settings['split_by'] == 0: self.widgets['rb_split_files'].set_active(True) else: self.widgets['rb_split_movies'].set_active(True) # posters self.widgets['combo_format'].set_active(0) if self.settings['poster_format'] == 'PNG': self.widgets['combo_format'].set_active(1) elif self.settings['poster_format'] == 'GIF': self.widgets['combo_format'].set_active(2) if self.settings['poster_convert'] and self.settings[ 'poster_convert'] == True: self.widgets['cb_convert'].set_active(True) self.widgets['vb_posters'].set_sensitive(True) else: self.widgets['cb_convert'].set_active(False) self.widgets['vb_posters'].set_sensitive(False) self.widgets['sb_height'].set_value(self.settings['poster_height']) self.widgets['sb_width'].set_value(self.settings['poster_width']) if self.settings['poster_mode'] == 'L': self.widgets['cb_black'].set_active(True) # destination dir if self.settings['export_dir']: self.widgets['fcw'].set_current_folder(self.settings['export_dir']) #}}} #==[ callbacks ]================================{{{ # buttons: def on_quit(self, widget=None): self.widgets['window'].destroy() # data tab -------------------------------------#{{{ def on_rb_split_files_toggled(self, widget): self.settings['split_by'] = 0 # files def on_rb_split_movies_toggled(self, widget): self.settings['split_by'] = 1 # movies # export frame def on_cb_data_toggled(self, widget): self.fields[gutils.after(widget.get_name(), 'cb_')] = widget.get_active() # posters frame def on_cb_convert_toggled(self, widget): active = widget.get_active() self.settings['poster_convert'] = active if not active: self.widgets['vb_posters'].set_sensitive(False) else: self.widgets['vb_posters'].set_sensitive(True) #}}} # template tab ---------------------------------#{{{ def on_combo_theme_changed(self, widget): old_id = self.settings['template'] tpl_id = widget.get_active() self.settings['template'] = tpl_id # fill authors data self.widgets['l_tpl_author'].set_markup( "<i>%s</i>" % self.templates[tpl_id]['author']) self.widgets['l_tpl_email'].set_markup("<i>%s</i>" % self.templates[tpl_id]['email']) self.widgets['l_tpl_email'].set_selectable(True) self.widgets['l_tpl_version'].set_markup( "<i>%s</i>" % self.templates[tpl_id]['version']) self.widgets['l_tpl_desc'].set_markup("<i>%s</i>" % self.templates[tpl_id]['desc']) # remove old style list self.widgets['combo_style'].get_model().clear() # ... and add new if self.templates[tpl_id]['styles'] is not None: for i in self.templates[tpl_id]['styles']: self.widgets['combo_style'].insert_text( i, self.templates[tpl_id]['styles'][i] ['name']) # template name self.widgets['combo_style'].set_active(0) else: self.settings['style'] = None self.widgets['image_preview'].set_from_stock( gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR) def on_combo_style_changed(self, widget): self.settings['style'] = widget.get_active() self.widgets['cb_custom_style'].set_active(False) preview_file = None tpl_id = self.settings['template'] template_dir = os.path.join(self.locations['share'], 'export_templates', self.templates[tpl_id]['dir']) if self.settings['style'] > -1: preview_file = self.templates[self.settings['template']]['styles'][ self.settings['style']]['preview'] if preview_file is not None: preview_file = os.path.join(template_dir, preview_file) if preview_file is not None and not os.path.isfile(preview_file): preview_file = os.path.join( template_dir, 'preview.jpg') # try default preview image if not os.path.isfile(preview_file): preview_file = None if preview_file is not None: self.widgets['image_preview'].set_from_file(preview_file) else: self.widgets['image_preview'].set_from_stock( gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR) self.widgets['image_preview'].show() def on_cb_custom_style_toggled(self, widget): if widget.get_active(): self.settings['custom_style'] = True self.widgets['image_preview'].hide() else: self.settings['custom_style'] = False self.widgets['image_preview'].show() def on_fcb_custom_style_file_activated(self, widget): self.settings['custom_style_file'] = widget.get_filename() self.widgets['cb_custom_style'].set_active(True) #}}} }}} def make_navigation(self, pages, current): #{{{ if pages > 1: # navigation needed tpl_id = self.settings['template'] t = '<div class="navi">\n\t<p id="prev">' if current > 1: t += '<a href="./page_%s.%s">%s</a>' % \ (str(current-1), self.templates[tpl_id]['ext'], _('previous')) else: # first page t += _('previous') t += "</p>\n" for i in range(1, pages + 1): if i == current: t += '\t<p id="current">%s</p>\n' % str(i) else: t +='\t<p><a href="./page_%s.%s">%s</a></p>\n' % \ (str(i), self.templates[tpl_id]['ext'], str(i)) t += '\t<p id="next">' if pages > current: t +='<a href="./page_%s.%s">%s</a>' % \ (str(current+1), self.templates[tpl_id]['ext'], _('next')) else: # last page t += _('next') t += "</p>\n</div>" return t else: return '' #}}} def fill_template(self, template, field, data='', title='', remove=False): #{{{ start = template.find('<@' + field + '>') end = template.find('</@' + field + '>', start + 1) if start > -1 and end > -1: if remove == True: return template[:start] + template[end + 4 + len(field):] else: tmp = gutils.trim(template, '<@' + field + '>', '</@' + field + '>') tmp = tmp.replace("@DATA@", data) tmp = tmp.replace("@TITLE@", title) tmp = template[:start] + tmp + template[end + 4 + len(field):] if tmp.find('<@' + field + '>') != -1: tmp = self.fill_template(tmp, field, data, title, remove) return tmp else: return template #}}} def select(self): #{{{ config = self.settings # sort order TODO: update self.search_conditions["sort_by"] tmp = config['sorting'].split('_') sort_column = "%s.%s" % (tmp[0], '_'.join(tmp[1:])) if config['sorting2'] == 'ASC': sort_column += ' ASC' else: sort_column += ' DESC' self.search_conditions["sort_by"] = (sort_column, ) query = self.get_query() return query.execute() #}}} #==[ main function ]============================{{{ def export_data(self, widget): """Main exporting function""" config = self.settings fields = self.fields tid = config['template'] # get data from widgets self.settings['export_dir'] = self.widgets['fcw'].get_filename() self.settings['title'] = self.widgets['entry_header'].get_text( ).decode('utf-8') self.settings['sorting'] = self.names[ self.widgets['combo_sortby'].get_active_text().decode('utf-8')] if self.widgets['cb_reverse'].get_active(): self.settings['sorting2'] = 'DESC' else: self.settings['sorting2'] = 'ASC' self.settings['split_num'] = self.widgets[ 'sb_split_num'].get_value_as_int() self.settings['poster_height'] = self.widgets[ 'sb_height'].get_value_as_int() self.settings['poster_width'] = self.widgets[ 'sb_width'].get_value_as_int() if self.widgets['cb_black'].get_active(): self.settings['poster_mode'] = 'L' else: self.settings['poster_mode'] = 'RGB' self.settings['poster_format'] = self.widgets[ 'combo_format'].get_active_text() # persist config if self.config is not None: for name, value in config.items(): self.config.set(name, value, section='export-html') selected_fields = '' for name, value in self.fields.items(): if value: selected_fields = selected_fields + name + ',' self.config.set('selected_fields', selected_fields, section='export-html') self.config.save() # create directories if not config['export_dir']: log.info("Error: Folder name not set!") return 1 if not os.path.isdir(config['export_dir']): try: os.mkdir(config['export_dir']) except: gutils.error(_("Can't create %s!") % config['export_dir']) return 2 data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data') if os.path.isdir(data_path): try: gutils.copytree(data_path, config['export_dir']) except Exception, err: gutils.warning(str(err)) if fields['movies_image']: # import modules needed later # modules are needed at least to convert griffith.png to nopic.(gif|jpeg|png) from PIL import Image # py2exe problem workaround: if os.name == 'nt' or os.name.startswith('win'): # win32, win64 from PIL import PngImagePlugin from PIL import GifImagePlugin from PIL import JpegImagePlugin Image._initialized = 2 if not config['poster_convert']: config['poster_format'] = 'jpeg' # replace 'jpeg' posters_dir = os.path.join(config['export_dir'], 'posters') if os.path.isdir(posters_dir): if gutils.question( _("Directory %s already exists.\nDo you want to overwrite it?" ) % posters_dir, self.widgets['window']): try: shutil.rmtree(posters_dir) except: gutils.error( _("Can't remove %s!") % config['export_dir']) return 3 else: return 4 try: os.mkdir(posters_dir) except: gutils.error(_("Can't create %s!") % posters_dir) return 5 if config['custom_style']: if config['custom_style_file'] is not None and os.path.isfile( config['custom_style_file']): try: shutil.copy(config['custom_style_file'], config['export_dir']) except: gutils.warning(_("Can't copy %s!") % style_file) config['custom_style'] = False style = os.path.split(self.settings['custom_style_file'])[1] else: config['custom_style'] = False if config['style'] is not None and config['custom_style'] == False: style = self.templates[tid]['styles'][config['style']]['file'] style_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], style) try: shutil.copy(style_path, config['export_dir']) except: gutils.warning(_("Can't copy %s!") % style_path) # select exported movies exported_movies = self.select().fetchall() if self.settings['sorting'] in ('movies_title', 'movies_o_title'): # re-sorting movies case-insensitive and respect the current locale setting # if sorting by title or original title is selected import locale locale.setlocale(locale.LC_ALL, "") exported_movies.sort(cmp = locale.strcoll, \ key = lambda k: k[self.settings['sorting']] and k[self.settings['sorting']].lower() or '', \ reverse = self.settings['sorting2']=='DESC') number_of_exported_movies = len(exported_movies) if config['split_by'] == 1: # split by number of movies per page self.entries_per_page = config['split_num'] else: # split by number of pagess if number_of_exported_movies < config['split_num']: self.entries_per_page = 1 else: self.entries_per_page = int(number_of_exported_movies / config['split_num']) # calculate number of files to be created (pages) self.pages = int( math.ceil( float(number_of_exported_movies) / self.entries_per_page)) template_dir = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir']) try: filename = 'page.tpl' tpl_header = file(os.path.join(template_dir, filename), "r").read() except: gutils.error(_("Can't open %s!") % filename) return False tpl_header = self.fill_template(tpl_header, 'header', config['title']) try: tpl_header = self.fill_template(tpl_header, 'style', style) except: pass tmp = _('Document generated by Griffith v') + version.pversion + \ ' - Copyright (C) ' + version.pyear + ' ' + version.pauthor + ' - ' + \ _('Released Under the GNU/GPL License') tmp = gutils.html_encode(tmp) tmp = tmp.replace('@', ' at ') # prevent spam tpl_header = self.fill_template(tpl_header, 'copyright', tmp) tmp = None tpl_header = self.fill_template(tpl_header, 'pages', self.pages) # count exported fields rowspan = 0 for i in fields: if fields[i] == True: rowspan = rowspan + 1 rowspan = str(rowspan) tpl_header = self.fill_template(tpl_header, 'rowspan', rowspan) # split template tpl_tail = gutils.after(tpl_header, '<!-- /ITEMS -->') tpl_item = gutils.trim(tpl_header, '<!-- ITEMS -->', '<!-- /ITEMS -->') tpl_header = gutils.before(tpl_header, '<!-- ITEMS -->') # fill header for j in self.names: if self.fields[self.names[j]] == True: tpl_header = self.fill_template(tpl_header, self.names[j], '', j) else: tpl_header = self.fill_template(tpl_header, self.names[j], remove=True) # check if line break needs conversion if tpl_header.upper().find('XHTML 1.0') > -1: linebreak_replacement = '<br />' else: linebreak_replacement = None item = 1 # item's position on page (1 - first, ...) i = 1 page = 1 # page number for row in exported_movies: # fill items {{{ # check if new file has to be created if item == 1: filename = os.path.join( config['export_dir'], 'page_%s.' % page + self.templates[tid]['ext']) try: exported_file = file(filename, 'w') except: gutils.error(_("Can't create %s!") % filename) return False tmp2 = tpl_header + '' exported_file.write(self.fill_template(tmp2, 'page', str(page))) tmp2 = None # --------------------------------------------- tmp = tpl_item + '' # a copy (not a reference!) tmp = self.fill_template(tmp, 'id', str(item)) tmp = self.fill_template(tmp, 'item', str(i)) for j in self.names: if self.fields[self.names[j]] == True: if self.names[j] == 'movies_image': if row['movies_poster_md5']: #image = row['movies_poster_md5'] + '.' + config['poster_format'].lower() image = "%d.%s" % (row['movies_number'], config['poster_format'].lower()) tmp = self.fill_template(tmp, self.names[j], image, j) else: tmp = self.fill_template( tmp, self.names[j], 'nopic.' + config['poster_format'].lower(), j) elif row[self.names[j]] is None: tmp = self.fill_template(tmp, self.names[j], '', j) elif row[self.names[j]] is True: tmp = self.fill_template(tmp, self.names[j], _('Yes'), j) elif row[self.names[j]] is False: tmp = self.fill_template(tmp, self.names[j], _('No'), j) else: try: data = str(row[self.names[j]]).encode('utf-8') if linebreak_replacement is not None: data = data.replace('\r\n', linebreak_replacement) data = data.replace('\n', linebreak_replacement) tmp = self.fill_template(tmp, self.names[j], data, j) except UnicodeDecodeError: log.info( "Unicode Decode Error occurred while decoding %s (movie number: %s)" % (self.names[j], row['movies_number'])) data = str(row[self.names[j]]) if linebreak_replacement is not None: data = data.replace('\r\n', linebreak_replacement) data = data.replace('\n', linebreak_replacement) tmp = self.fill_template(tmp, self.names[j], data, j) except Exception, ex: log.info( "Error occurred while decoding %s (movie number: %s)" % (self.names[j], row['movies_number'])) else: tmp = self.fill_template(tmp, self.names[j], remove=True) tmp = gutils.convert_entities(tmp) exported_file.write(tmp) tmp = None # --------------------------------------------- # copy poster if fields['movies_image']: if row['movies_poster_md5']: image_file_src = gutils.get_image_fname( row['movies_poster_md5'], self.db) image_file_dst = os.path.join( posters_dir, "%d.%s" % (row['movies_number'], config['poster_format'].lower())) if not config['poster_convert']: # copy file try: shutil.copy(image_file_src, image_file_dst) except: log.info("Can't copy %s", image_file_src) else: # convert posters try: im = Image.open(image_file_src, 'r').convert(config['poster_mode']) im.thumbnail((config['poster_width'], config['poster_height']), Image.ANTIALIAS) im.save(image_file_dst, config['poster_format']) except: log.info("Can't convert %s", image_file_src) # close file if last item if ((page - 1) * self.entries_per_page) + item == number_of_exported_movies: tmp2 = tpl_tail + '' exported_file.write( self.fill_template(tmp2, 'navigation', self.make_navigation(self.pages, page))) exported_file.close() tmp2 = None # close file if last item in page elif item == self.entries_per_page: tmp2 = tpl_tail + '' exported_file.write( self.fill_template(tmp2, 'navigation', self.make_navigation(self.pages, page))) exported_file.close() page = page + 1 item = 1 tmp2 = None else: item = item + 1 i = i + 1
def export_data(self, widget): """Main exporting function""" config = self.settings fields = self.fields tid = config['template'] # get data from widgets self.settings['export_dir'] = self.widgets['fcw'].get_filename() self.settings['title'] = self.widgets['entry_header'].get_text( ).decode('utf-8') self.settings['sorting'] = self.names[ self.widgets['combo_sortby'].get_active_text().decode('utf-8')] if self.widgets['cb_reverse'].get_active(): self.settings['sorting2'] = 'DESC' else: self.settings['sorting2'] = 'ASC' self.settings['split_num'] = self.widgets[ 'sb_split_num'].get_value_as_int() self.settings['poster_height'] = self.widgets[ 'sb_height'].get_value_as_int() self.settings['poster_width'] = self.widgets[ 'sb_width'].get_value_as_int() if self.widgets['cb_black'].get_active(): self.settings['poster_mode'] = 'L' else: self.settings['poster_mode'] = 'RGB' self.settings['poster_format'] = self.widgets[ 'combo_format'].get_active_text() # persist config if self.config is not None: for name, value in config.items(): self.config.set(name, value, section='export-html') selected_fields = '' for name, value in self.fields.items(): if value: selected_fields = selected_fields + name + ',' self.config.set('selected_fields', selected_fields, section='export-html') self.config.save() # create directories if not config['export_dir']: log.info("Error: Folder name not set!") return 1 if not os.path.isdir(config['export_dir']): try: os.mkdir(config['export_dir']) except: gutils.error(_("Can't create %s!") % config['export_dir']) return 2 data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data') if os.path.isdir(data_path): try: gutils.copytree(data_path, config['export_dir']) except Exception, err: gutils.warning(str(err))
def get_poster(self, f, result, current_poster): if f == None: treeselection = self.results_treeview.get_selection() (tmp_model, tmp_iter) = treeselection.get_selected() f = int(tmp_model.get_value(tmp_iter, 0)) self.w_results.hide() file_to_copy = tempfile.mktemp(suffix=self.e_number.get_text(), prefix='poster_', \ dir=os.path.join(self.griffith_dir, "posters")) file_to_copy += ".jpg" try: progress = movie.Progress(self.main_window,_("Fetching poster"),_("Wait a moment")) retriever = movie.Retriever(result[f].ImageUrlLarge, self.main_window, progress, file_to_copy) retriever.start() while retriever.isAlive(): progress.pulse() if progress.status: retriever.suspend() while gtk.events_pending(): gtk.main_iteration() progress.close() urlcleanup() except: gutils.warning(self, _("Sorry. A connection error was occurred.")) self.debug.show(file_to_copy) if os.path.isfile(file_to_copy): handler = self.big_poster.set_from_file(file_to_copy) gutils.garbage(handler) try: im = Image.open(file_to_copy) except IOError: self.debug.show("failed to identify %s"%file_to_copy) else: if im.format == "GIF": gutils.warning(self, _("Sorry. This poster image format is not supported.")) os.remove(file_to_copy) return self.poster_window.show() self.poster_window.move(0,0) response = \ gutils.question(self, \ _("Do you want to use this poster instead?"), \ 1, self.main_window) if response == -8: self.debug.show("Using new fetched poster, updating and removing old one from disk.") update.update_image(self, os.path.basename(file_to_copy), self.e_number.get_text()) gutils.make_thumbnail(self, '%s' % os.path.basename(file_to_copy)) gutils.make_medium_image(self, '%s' % os.path.basename(file_to_copy)) update_tree_thumbnail(self, '%s/posters/t_%s' % (self.griffith_dir, \ os.path.basename(file_to_copy))) self.e_picture.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(os.path.join(self.griffith_dir, "posters/m_%s"%os.path.basename(file_to_copy)))) delete.delete_poster(self, current_poster) else: self.debug.show("Reverting to previous poster and deleting new one from disk.") try: os.remove(file_to_copy) except: self.debug.show("no permission for %s"%file_to_copy) self.poster_window.hide() else: gutils.warning(self, _("Sorry. This movie is listed but have no poster available at Amazon.com."))
def __init__(self, config, griffith_dir, fallback=True): #mapper = Session.mapper self.config = config self.data_dir = griffith_dir if config.get('type', None, section='database') is None: config.set('type', 'sqlite', section='database') if config.get('type', 'sqlite', section='database') != 'sqlite': if config.get('host', None, section='database') is None: config.set('host', '127.0.0.1', section='database') if config.get('user', None, section='database') is None: config.set('user', 'griffith', section='database') if config.get('passwd', None, section='database') is None: config.set('passwd', 'gRiFiTh', section='database') if config.get('name', None, section='database') is None: config.set('name', 'griffith', section='database') if config.get('port', 0, section='database') == 0: config.set('port', GriffithSQL.DEFAULT_PORTS[config.get( 'type', section='database')], section='database') conn_params = config.to_dict(section='database') conn_params.update({ 'port': int(conn_params.get('port', 0)), 'engine_kwargs': { 'echo': False, 'convert_unicode': False } }) # connect to database --------------------------------------{{{ dbinitializingsql = None if config.get('type', section='database') == 'sqlite': sqlitefile = "%s.db" % os.path.join(griffith_dir, conn_params['name']) if not os.path.isfile(sqlitefile): # for new created database this is an optimization step syncing the database page size # to the filesystem page size dbinitializingsql = 'PRAGMA page_size=' + str( get_filesystem_pagesize(sqlitefile)) url = "sqlite:///%s" % sqlitefile elif config.get('type', section='database') == 'postgres': # sqlalchemy version check because postgres dialect is renamed in sqlalchemy>=0.6 from postgres to postgresql from sqlalchemy import __version__ as sqlalchemyversion if map(int, sqlalchemyversion[:3].split('.')) < [0, 6]: url = "postgres" else: url = "postgresql" url = url + "://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s" % conn_params elif config.get('type', section='database') == 'mysql': conn_params['engine_kwargs']['convert_unicode'] = True conn_params['engine_kwargs']['pool_recycle'] = int( config.get('pool_recycle', 3600, section='database')) url = "mysql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?charset=utf8&use_unicode=0" % conn_params elif config.get('type', section='database') == 'mssql': # use_scope_identity=0 have to be set as workaround for a sqlalchemy bug # but it is not guaranteed that the right identity value will be selected # because the select @@identity statement selects the very last id which # also can be a id from a trigger-insert or another user # sqlalchemy uses a wrong syntax. It has to select the id within the insert # statement: insert <table> (<columns>) values (<values>) select scope_identity() # (one statement !) After preparing and executing there should be a fetch # If it is executed as two separate statements the scope is lost after insert. url = "mssql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?use_scope_identity=0" % conn_params else: config.set('type', 'sqlite', section='database') url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name']) # try to establish a db connection try: engine = create_engine(url, **conn_params['engine_kwargs']) conn = engine.connect() if dbinitializingsql is not None: engine.execute(dbinitializingsql) except Exception, e: # InvalidRequestError, ImportError log.info("MetaData: %s", e) if not fallback: raise e config.set('type', 'sqlite', section='database') warning("%s\n\n%s" % (_('Cannot connect to database.\nFalling back to SQLite.'), _('Please check debug output for more informations.'))) url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name']) engine = create_engine(url) conn = engine.connect()
log.info(e) v = 0 except Exception, e: log.error(e) v = 0 if v is not None and v > 1: v = int(v.value) if v < self.version: from dbupgrade import upgrade_database if not upgrade_database(self, v, config): raise Exception('cannot upgrade database') elif v > self.version: log.error("database version mismatch (detected:%s; current:%s)", v, self.version) warning(_('This database requires newer version of Griffith.')) raise Exception("database version mismatch") def dispose(self): # close every session and connection so that a sqlite database file can be removed # otherwise it will remain opened by the current process and can't be deleted try: self.session.close() self.Session.close_all() self.engine.dispose() del self.session del self.Session del self.engine except: log.exception('')
def get_poster(self, item): """Returns file path to the new poster""" from movie import Progress, Retriever file_to_copy = tempfile.mktemp(suffix=self.widgets['movie']['number'].get_text(), \ dir=self.locations['temp']) file_to_copy += ".jpg" canceled = False try: progress = Progress(self.widgets['window'], _("Fetching poster"), _("Wait a moment")) retriever = Retriever(item.LargeImage.URL, self.widgets['window'], progress, file_to_copy) retriever.start() while retriever.isAlive(): progress.pulse() if progress.status: canceled = True while gtk.events_pending(): gtk.main_iteration() progress.close() urlcleanup() except: canceled = True gutils.warning(_("Sorry. A connection error has occurred.")) try: os.remove(file_to_copy) except: log.error("no permission for %s" % file_to_copy) if not canceled: if os.path.isfile(file_to_copy): im = None try: im = Image.open(file_to_copy) except IOError: log.warn("failed to identify %s" % file_to_copy) if im and im.size == (1, 1): url = FancyURLopener().open("http://www.amazon.com/gp/product/images/%s" % item.ASIN).read() if url.find('no-img-sm._V47056216_.gif') > 0: log.warn('No image available') gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com.")) return False url = gutils.after(url, 'id="imageViewerDiv"><img src="') url = gutils.before(url, '" id="prodImage"') urlretrieve(url, file_to_copy) try: im = Image.open(file_to_copy) except IOError: log.warn("failed to identify %s", file_to_copy) if not im: # something wrong with the image, give some feedback to the user log.warn('No image available') gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com.")) return False if im.mode != 'RGB': # convert GIFs im = im.convert('RGB') im.save(file_to_copy, 'JPEG') # set to None because the file is locked otherwise (os.remove throws an exception) im = None handler = self.widgets['big_poster'].set_from_file(file_to_copy) self.widgets['poster_window'].show() self.widgets['poster_window'].move(0, 0) if gutils.question(_("Do you want to use this poster instead?"), self.widgets['window']): return file_to_copy else: log.info("Reverting to previous poster and deleting new one from disk.") try: os.remove(file_to_copy) except: log.error('cannot remove %s', file_to_copy) self.widgets['poster_window'].hide() else: gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com.")) else: # cleanup temporary files after canceling the download if os.path.isfile(file_to_copy): try: os.remove(file_to_copy) except: log.error('cannot remove %s', file_to_copy)
def toolbar_icon_clicked(self, widget, movie): log.info('fetching poster from Amazon...') self.movie = movie locale = self.get_config_value('locale', 'US').lower() accesskey = self.get_config_value('accesskey') secretkey = self.get_config_value('secretkey') if not accesskey or not secretkey: gutils.error(_('Please configure your Amazon Access Key ID and Secret Key correctly in the preferences dialog.')) return False if movie is None: gutils.error(_('You have no movies in your database'), self.widgets['window']) return False keyword = movie.o_title if locale == 'de': keyword = movie.title try: amazon.setLicense(accesskey, secretkey) result = amazon.searchByTitle(keyword, type='Large', product_line='DVD', locale=locale) if hasattr(result, 'TotalPages'): # get next result pages pages = int(result.TotalPages) page = 2 while page <= pages and page < 11: tmp = amazon.searchByTitle(keyword, type='Large', product_line='DVD', locale=locale, page=page) result.Item.extend(tmp.Item) page = page + 1 if not hasattr(result, 'Item') or not len(result.Item): # fallback if nothing is found by title result = amazon.searchByKeyword(keyword, type='Large', product_line='DVD', locale=locale) if hasattr(result, 'TotalPages'): # get next result pages pages = int(result.TotalPages) page = 2 while page <= pages and page < 11: tmp = amazon.searchByKeyword(keyword, type='Large', product_line='DVD', locale=locale, page=page) result.Item.extend(tmp.Item) page = page + 1 self._result = result log.info("... %s posters found" % result.TotalResults) except: log.exception('') gutils.warning(_('No posters found for this movie.')) return if not hasattr(result, 'Item') or not len(result.Item): gutils.warning(_('No posters found for this movie.')) return if len(result.Item) == 1: o_title = self.widgets['movie']['o_title'].get_text().decode('utf-8') if o_title == result.Item[0].ItemAttributes.Title or keyword == result.Item[0].ItemAttributes.Title: self.get_poster(self.app, result.Item[0]) return # populate results window items = {} for i, item in enumerate(result.Item): if hasattr(item, 'LargeImage') and len(item.LargeImage.URL): title = item.ItemAttributes.Title if hasattr(item.ItemAttributes, 'ProductGroup'): title = title + u' - ' + item.ItemAttributes.ProductGroup elif hasattr(item.ItemAttributes, 'Binding'): title = title + u' - ' + item.ItemAttributes.Binding if hasattr(item.ItemAttributes, 'ReleaseDate'): title = title + u' - ' + item.ItemAttributes.ReleaseDate[:4] elif hasattr(item.ItemAttributes, 'TheatricalReleaseDate'): item.ItemAttributes.TheatricalReleaseDate[:4] if hasattr(item.ItemAttributes, 'Studio'): title = title + u' - ' + item.ItemAttributes.Studio items[i] = title populate_results_window(self.app.treemodel_results, items) self.widgets['add']['b_get_from_web'].set_sensitive(False) # disable movie plugins (result window is shared) self.app._resultswin_process = self.on_result_selected # use this signal (will be reverted when window is closed) self.widgets['results']['window'].show() self.widgets['results']['window'].set_keep_above(True)
def toolbar_icon_clicked(self, widget, movie): log.info('fetching poster from MoviePosterDB.com...') self.movie = movie # correction of the movie name for the search o_title = None title = None if movie.o_title: if movie.o_title.endswith(', The'): o_title = u"The %s" % movie.o_title[:-5] else: o_title = movie.o_title if movie.title: if movie.title.endswith(', The'): title = u"The %s" % movie.title[:-5] else: title = movie.title # try to get an url to the large version of a poster for the movie # (requests are in the order: # original title + year, original title only, title + year, title only) try: largeurl = None data = False if o_title: if movie.year: url = self.baseurltitleyear % (o_title, movie.year) data = self._get(url, self.widgets['window']) if data and data.find('movie/0000000') < 0: largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_') if not data or not largeurl: url = self.baseurltitle % o_title data = self._get(url, self.widgets['window']) if data and data.find('movie/0000000') < 0: largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_') if not data or not largeurl and title and title != o_title: if movie.year: url = self.baseurltitleyear % (title, movie.year) data = self._get(url, self.widgets['window']) if data and data.find('movie/0000000') < 0: largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_') if not data or not largeurl: url = self.baseurltitle % title data = self._get(url, self.widgets['window']) if data and data.find('movie/0000000') < 0: largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_') except: log.exception('') gutils.warning(_('No posters found for this movie.')) return if not data or not largeurl: gutils.warning(_('No posters found for this movie.')) return # got the url for a large poster, fetch the data, show preview and update the # movie entry if the user want it data = self._get(largeurl, self.widgets['window'], decode=False) if not data: gutils.warning(_('No posters found for this movie.')) return if self._show_preview(data): update_image_from_memory(self.app, movie.number, data)