def on_import_button_clicked(button, self, *args): import plugins.imp import gutils plugin_name = self.widgets['import']['plugin'].get_active_text() filenames = self.widgets['import']['fcw'].get_filenames() fields = [] w = self.widgets['import']['fields'] for i in w: if w[i].get_active(): fields.append(i) __import__("plugins.imp.%s" % plugin_name) if self.debug_mode: log.debug('reloading %s', plugin_name) import sys reload(sys.modules["plugins.imp.%s" % plugin_name]) ip = eval("plugins.imp.%s.ImportPlugin(self, fields)" % plugin_name) if ip.initialize(): self.widgets['window'].set_sensitive(False) try: self.widgets['import']['window'].hide() self.widgets['import']['pabort'].connect('clicked', ip.abort, ip) for filename in filenames: self.widgets['import']['progressbar'].set_fraction(0) self.widgets['import']['progressbar'].set_text('') if ip.run(filename): gutils.info(_("%s file has been imported. %s movies added.") \ % (plugin_name, ip.imported), self.widgets['window']) self.populate_treeview() ip.clear() except Exception, e: log.exception('') gutils.error(str(e), self.widgets['window']) finally:
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): 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 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 show_websearch_results(self): total = self.founded_results_id = 0 for g in self.search_movie.ids: if (str(g) != ''): total += 1 if total > 1: self.widgets['results']['window'].show() self.widgets['results']['window'].set_keep_above(True) row = None key = 0 self.treemodel_results.clear() for row in self.search_movie.ids: if (str(row) != ''): if isinstance(self.search_movie.titles[key], unicode): title = self.search_movie.titles[key] else: title = str(self.search_movie.titles[key]).decode( self.search_movie.encode) myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(row)) self.treemodel_results.set_value(myiter, 1, title) key += 1 self.widgets['results']['treeview'].show() elif total == 1: self.widgets['results']['treeview'].set_cursor(total - 1) for row in self.search_movie.ids: if (str(row) != ''): self.founded_results_id = str(row) populate_with_results(self) else: gutils.error(_("No results"), self.widgets['add']['window'])
def do_test_searchplugin(self, plugin_name, domsgbox=True): result = True plugin = __import__(plugin_name) try: pluginTestConfig = plugin.SearchPluginTest() except: print "Warning: SearchPlugin test could not be executed for %s because of missing configuration class SearchPluginTest." % plugin_name pluginTestConfig = None if not pluginTestConfig == None: logFile = open(plugin_name + "-searchtest.txt", "w+") try: for i in pluginTestConfig.test_configuration: searchPlugin = plugin.SearchPlugin() if not self.test_search( searchPlugin, logFile, i, pluginTestConfig.test_configuration[i][0], pluginTestConfig.test_configuration[i][1], ): result = False sleep(1) # needed for amazon finally: logFile.close() if domsgbox: if not result: gutils.error(self, "SearchPluginTest %s: Test NOT successful !" % plugin_name) else: gutils.info("SearchPluginTest %s: Test successful !" % plugin_name) return result
def show_websearch_results(self): total = self.founded_results_id = 0 for g in self.search_movie.ids: if (str(g) != ''): total += 1 if total > 1: self.widgets['results']['window'].show() self.widgets['results']['window'].set_keep_above(True) movieslist = [] row = None key = 0 for row in self.search_movie.ids: if (str(row) != ''): if isinstance(self.search_movie.titles[key], unicode): title = self.search_movie.titles[key] else: title = str(self.search_movie.titles[key]).decode(self.search_movie.encode) movieslist.append((row, title)) key += 1 movieslist = sorted(movieslist, key=lambda titel: titel[1]) self.treemodel_results.clear() for entry in movieslist: myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(entry[0])) self.treemodel_results.set_value(myiter, 1, entry[1]) self.widgets['results']['treeview'].show() elif total == 1: self.widgets['results']['treeview'].set_cursor(total-1) for row in self.search_movie.ids: if (str(row) != ''): self.founded_results_id = str(row) populate_with_results(self) else: gutils.error(_("No results"), self.widgets['add']['window'])
def restore(self): """restores a griffith compressed backup""" filename = gutils.file_chooser(_("Restore Griffith backup"), \ action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons= \ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, \ gtk.STOCK_OPEN, gtk.RESPONSE_OK)) if filename[0]: try: zip = zipfile.ZipFile(filename[0], 'r') except: gutils.error(self, _("Can't read backup file"), self.widgets['window']) return False mypath = os.path.join(self.locations['posters']) for each in zip.namelist(): file_to_restore = os.path.split(each) if not os.path.isdir(file_to_restore[1]): if file_to_restore[1] == '': continue if file_to_restore[1].endswith('.jpg'): myfile = os.path.join(mypath,file_to_restore[1]) else: myfile = os.path.join(self.locations['home'],file_to_restore[1]) outfile = open(myfile, 'wb') outfile.write(zip.read(each)) outfile.flush() outfile.close() zip.close() # restore config file self.config = config.Config(file=os.path.join(self.locations['home'],'griffith.conf')) filename = os.path.join(self.locations['home'], self.config["default_db"]) self.db.metadata.engine.dispose() # close DB from sqlalchemy.orm import clear_mappers clear_mappers() # check if file needs conversion if self.config['default_db'].lower().endswith('.gri'): self.debug.show('Old database format detected. Converting...') from dbupgrade import convert_from_old_db from initialize import location_posters if convert_from_old_db(self, filename, os.path.join(self.locations['home'], 'griffith.db')): self.config.save() location_posters(self.locations, self.config) else: print 'Cant convert old database, exiting.' import sys sys.exit(4) self.db = sql.GriffithSQL(self.config, self.debug, self.locations['home']) from initialize import dictionaries, people_treeview dictionaries(self) people_treeview(self) # let's refresh the treeview self.clear_details() self.populate_treeview() self.go_last() self.treeview_clicked() self.count_statusbar() gutils.info(self, _("Backup restored"), self.widgets['window'])
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 get_from_web(self): """search the movie in web using the active plugin""" title = self.widgets['add']['title'].get_text() o_title = self.widgets['add']['o_title'].get_text() if o_title or title: option = gutils.on_combo_box_entry_changed_name(self.widgets['add']['source']) self.active_plugin = option plugin_name = 'PluginMovie%s' % option plugin = __import__(plugin_name) self.search_movie = plugin.SearchPlugin() if o_title: self.search_movie.url = self.search_movie.original_url_search self.search_movie.title = gutils.remove_accents(o_title, 'utf-8') elif title: self.search_movie.url = self.search_movie.translated_url_search self.search_movie.title = gutils.remove_accents(title, 'utf-8') self.search_movie.search(self.widgets['add']['window']) self.search_movie.get_searches() if len(self.search_movie.ids) == 1 and o_title and title: self.search_movie.url = self.search_movie.translated_url_search self.search_movie.title = gutils.remove_accents(title, 'utf-8') self.search_movie.search(self.widgets['add']['window']) self.search_movie.get_searches() self.show_search_results(self.search_movie) else: gutils.error(self.widgets['results']['window'], \ _("You should fill the original title\nor the movie title."))
def do_test_plugin(self, plugin_name, domsgbox=True): result = True plugin = __import__(plugin_name) try: pluginTestConfig = plugin.PluginTest() except: print "Warning: Plugin test could not be executed for %s because of missing configuration class PluginTest." % plugin_name pluginTestConfig = None if not pluginTestConfig == None: logFile = open(plugin_name + '-loadtest.txt', 'w+') try: for i in pluginTestConfig.test_configuration: moviePlugin = plugin.Plugin(i) if not self.test_one_movie(moviePlugin, logFile, pluginTestConfig.test_configuration[i]): result = False sleep(1) # needed for amazon finally: logFile.close() if domsgbox: if not result: gutils.error(self, 'PluginTest %s: Test NOT successful !' % plugin_name) else: gutils.info(self, 'PluginTest %s: Test successful !' % plugin_name) return result
def show_websearch_results(self): total = self.founded_results_id = 0 for g in self.search_movie.ids: if ( str(g) != '' ): total += 1 if total > 1: self.widgets['results']['window'].show() self.widgets['results']['window'].set_keep_above(True) row = None key = 0 self.treemodel_results.clear() for row in self.search_movie.ids: if (str(row)!=''): title = str(self.search_movie.titles[key]).decode(self.search_movie.encode) myiter = self.treemodel_results.insert_before(None, None) self.treemodel_results.set_value(myiter, 0, str(row)) self.treemodel_results.set_value(myiter, 1, title) key +=1 self.widgets['results']['treeview'].show() elif total==1: self.widgets['results']['treeview'].set_cursor(total-1) for row in self.search_movie.ids: if ( str(row) != '' ): self.founded_results_id = str(row) populate_with_results(self) else: gutils.error(self.widgets['results']['window'], _("No results"), self.widgets['add']['window'])
def do_test_plugin(self, plugin_name, domsgbox=True): result = True plugin = __import__(plugin_name) try: pluginTestConfig = plugin.PluginTest() except: print "Warning: Plugin test could not be executed for %s because of missing configuration class PluginTest." % plugin_name pluginTestConfig = None if not pluginTestConfig == None: logFile = open(plugin_name + '-loadtest.txt', 'w+') try: for i in pluginTestConfig.test_configuration: moviePlugin = plugin.Plugin(i) if not self.test_one_movie( moviePlugin, logFile, pluginTestConfig.test_configuration[i]): result = False sleep(1) # needed for amazon finally: logFile.close() if domsgbox: if not result: gutils.error('PluginTest %s: Test NOT successful !' % plugin_name) else: gutils.info('PluginTest %s: Test successful !' % plugin_name) return result
def add_movie_db(self, close): if len(self.am_original_title.get_text()) or len(self.am_title.get_text()): self.db.add_movie(self) # lets move poster from tmp to posters dir tmp_dest = os.path.join(self.griffith_dir, "posters") if self.windows: temp_dir = "C:\\windows\\temp\\" else: temp_dir = "/tmp/" pic = string.replace(self.am_picture_name.get_text()+".jpg",temp_dir,"") if len(self.am_picture_name.get_text()): if os.path.isfile(os.path.join(temp_dir, pic)): shutil.move(os.path.join(temp_dir, pic), tmp_dest) if int(self.am_number.get_text()) >= 2: insert_after = self.treemodel.get_iter(int(self.am_number.get_text())-2) else: insert_after = None myiter = self.treemodel.insert_after(None, insert_after) if len(self.am_picture_name.get_text()): image_path = os.path.join(tmp_dest, pic) #lets make the thumbnail and medium image from poster for future use gutils.make_thumbnail(self, image_path) gutils.make_medium_image(self, image_path) else: image_path = os.path.join(self.locations['images'], "default.png") handler = self.Image.set_from_file(image_path) pixbuf = self.Image.get_pixbuf() self.treemodel.set_value(myiter, 1, \ '%004d' % int(self.am_number.get_text())) self.treemodel.set_value(myiter, 2, pixbuf.scale_simple(30,40,3)) self.treemodel.set_value(myiter, \ 3, str(self.am_original_title.get_text())) self.treemodel.set_value(myiter, 4, str(self.am_title.get_text())) self.treemodel.set_value(myiter, 5, str(self.am_director.get_text())) #update statusbar self.total += 1 self.total_filter = self.total self.count_statusbar() #select new entry from main treelist treeselection = self.main_treeview.get_selection() treeselection.select_iter(myiter) self.main_treeview.set_cursor(int(self.am_number.get_text())-1) self.treeview_clicked() next_number=gutils.find_next_available(self) initialize_add_dialog(self) self.am_number.set_text(str(next_number)) if close: self.hide_add_movie() else: gutils.error(self.w_results, \ _("You should fill the original title\nor the movie title."))
def set_source(self, name): IP.set_source(self, name) self.filename = name self.fileversion = self.read_fileversion() if self.fileversion == None: gutils.error(_('The format of the file is not supported.')) return False return 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, 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 update_image(self, number, file_path): import shutil try: self.widgets['movie']['picture'].set_from_pixbuf(\ gtk.gdk.pixbuf_new_from_file(file_path).scale_simple(100, 140, gtk.gdk.INTERP_BILINEAR)) except Exception, e: self.debug.show(str(e)) gutils.error(self, _("Image not valid."), self.widgets['window']) return False
def update_image(self, number, filename): session = self.db.Session() try: self.widgets['movie']['picture'].set_from_pixbuf(\ gtk.gdk.pixbuf_new_from_file(filename).scale_simple(100, 140, gtk.gdk.INTERP_BILINEAR)) except Exception, e: log.error(str(e)) gutils.error(self, _("Image is not valid."), self.widgets['window']) 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) 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 change_poster(self): """ changes movie poster image to a custom one showing a file chooser dialog to select it """ number = int(self.selected[0]) if number is None: gutils.error(_("You have no movies in your database"), self.widgets["window"]) return False return change_poster_select_file(self, number)
def change_poster(self): """ changes movie poster image to a custom one showing a file chooser dialog to select it """ number = int(self.selected[0]) if number is None: gutils.error(_("You have no movies in your database"), self.widgets['window']) return False return change_poster_select_file(self, number)
def add_movie_db(self, close): session = self.db.Session() details = get_details(self) if not details['o_title'] and not details['title']: gutils.error( _("You should fill the original title\nor the movie title."), parent=self.widgets['add']['window']) return False asked = False if details['o_title']: if session.query( db.Movie).filter_by(o_title=details['o_title']).count() > 0: asked = True if not gutils.question( _('Movie with that title already exists, are you sure you want to add?' ), self.widgets['add']['window']): return False if not asked and details['title']: if session.query( db.Movie).filter_by(title=details['title']).count() > 0: if not gutils.question( _('Movie with that title already exists, are you sure you want to add?' ), self.widgets['add']['window']): return False new_poster_md5 = None if details['image']: tmp_image_path = details['image'] if not os.path.isfile(tmp_image_path): tmp_image_path = os.path.join(self.locations['temp'], "poster_%s.jpg" % details['image']) if os.path.isfile(tmp_image_path): new_poster_md5 = gutils.md5sum(file(tmp_image_path, 'rb')) if session.query( db.Poster).filter_by(md5sum=new_poster_md5).count() == 0: try: data = file(tmp_image_path, 'rb').read() except Exception, e: log.warning("cannot read poster data") else: poster = db.Poster(md5sum=new_poster_md5, data=data) del details["image"] details["poster_md5"] = new_poster_md5 session.add(poster) else: details["poster_md5"] = new_poster_md5 try: if not tmp_image_path == details['image']: os.remove(tmp_image_path) except Exception, e: log.warn("cannot remove temporary file %s", tmp_image_path)
def get_from_web(self): """search the movie in web using the active plugin""" title = self.widgets['add']['title'].get_text() o_title = self.widgets['add']['o_title'].get_text() if o_title or title: option = gutils.on_combo_box_entry_changed_name( self.widgets['add']['source']) self.active_plugin = option plugin_name = 'PluginMovie%s' % option plugin = __import__(plugin_name) if self.debug_mode: log.debug('reloading %s', plugin_name) import sys reload(sys.modules[plugin_name]) self.search_movie = plugin.SearchPlugin() self.search_movie.config = self.config self.search_movie.locations = self.locations if o_title: self.search_movie.url = self.search_movie.original_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents( o_title, 'utf-8') else: self.search_movie.title = unicode(o_title, 'utf-8') elif title: self.search_movie.url = self.search_movie.translated_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents(title, 'utf-8') else: self.search_movie.title = unicode(title, 'utf-8') # check if internet connection is available try: urllib2.urlopen(self.search_movie.url) if self.search_movie.search_movies(self.widgets['add']['window']): self.search_movie.get_searches() if len(self.search_movie.ids) == 1 and o_title and title: self.search_movie.url = self.search_movie.translated_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents( title, 'utf-8') else: self.search_movie.title = unicode(title, 'utf-8') if self.search_movie.search_movies( self.widgets['add']['window']): self.search_movie.get_searches() self.show_search_results(self.search_movie) except: log.exception('') gutils.error(_("Connection failed.")) else: gutils.error( _("You should fill the original title\nor the movie title."))
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 update_image_from_memory(self, number, data): session = self.db.Session() try: loader = gtk.gdk.PixbufLoader() loader.write(data, len(data)) loader.close() self.widgets['movie']['picture'].set_from_pixbuf(\ loader.get_pixbuf().scale_simple(100, 140, gtk.gdk.INTERP_BILINEAR)) except Exception, e: log.error(str(e)) gutils.error(_("Image is not valid."), self.widgets['window']) return False
def set_source(self, name): IP.set_source(self, name) self.filename = name self.fileversion = self.read_fileversion() if self.fileversion == None: gutils.error(_('The format of the file is not supported.')) return False if self.filename: self.imdbfilename = os.path.join(os.path.dirname(self.filename), 'IMDb.dat') else: self.imdbfilename = None return True
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 add_person_db(self): if self.widgets["person"]["name"].get_text() <> "": p = self.db.Person() p.name = self.widgets["person"]["name"].get_text() p.email = self.widgets["person"]["email"].get_text() p.phone = self.widgets["person"]["phone"].get_text() self.widgets["person"]["window"].hide() if p.add_to_db(): myiter = self.p_treemodel.insert_after(None, None) self.p_treemodel.set_value(myiter, 0, str(self.widgets["person"]["name"].get_text())) self.p_treemodel.set_value(myiter, 1, str(self.widgets["person"]["email"].get_text())) self.widgets["people"]["window"].present() else: gutils.error(self.widgets["results"]["window"], _("You should fill the person name"))
def change_poster(self): """ changes movie poster image to a custom one showing a file chooser dialog to select it """ picture = self.widgets['movie']['picture'] number = self.get_maintree_selection()[0] if number is None: gutils.error(self,_("You have no movies in your database"), self.widgets['window']) return False filename = gutils.file_chooser(_("Select image"), action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK), name="", folder=self.locations['desktop'], picture=True) if filename and filename[0]: filename = filename[0].decode('UTF-8') update_image(self, number, filename)
def add_person_db(self): if (self.widgets['person']['name'].get_text()<>''): p = self.db.Person() p.name = self.widgets['person']['name'].get_text() p.email = self.widgets['person']['email'].get_text() p.phone = self.widgets['person']['phone'].get_text() self.widgets['person']['window'].hide() if p.add_to_db(): myiter = self.p_treemodel.insert_after(None, None) self.p_treemodel.set_value(myiter,0,str(self.widgets['person']['name'].get_text())) self.p_treemodel.set_value(myiter,1,str(self.widgets['person']['email'].get_text())) self.widgets['people']['window'].present() else: gutils.error(self.widgets['results']['window'],_("You should fill the person name"))
def get_from_web(self): """search the movie in web using the active plugin""" title = self.widgets['add']['title'].get_text() o_title = self.widgets['add']['o_title'].get_text() if o_title or title: option = gutils.on_combo_box_entry_changed_name(self.widgets['add']['source']) self.active_plugin = option plugin_name = 'PluginMovie%s' % option plugin = __import__(plugin_name) if self.debug_mode: log.debug('reloading %s', plugin_name) import sys reload(sys.modules[plugin_name]) self.search_movie = plugin.SearchPlugin() self.search_movie.config = self.config self.search_movie.locations = self.locations if o_title: self.search_movie.url = self.search_movie.original_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents(o_title, 'utf-8') else: self.search_movie.title = unicode(o_title, 'utf-8') elif title: self.search_movie.url = self.search_movie.translated_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents(title, 'utf-8') else: self.search_movie.title = unicode(title, 'utf-8') # check if internet connection is available try: urllib2.urlopen("http://www.griffith.cc") if self.search_movie.search_movies(self.widgets['add']['window']): self.search_movie.get_searches() if len(self.search_movie.ids) == 1 and o_title and title: self.search_movie.url = self.search_movie.translated_url_search if self.search_movie.remove_accents: self.search_movie.title = gutils.remove_accents(title, 'utf-8') else: self.search_movie.title = unicode(title, 'utf-8') if self.search_movie.search_movies(self.widgets['add']['window']): self.search_movie.get_searches() self.show_search_results(self.search_movie) except: log.exception('') gutils.error(_("Connection failed.")) else: gutils.error(_("You should fill the original title\nor the movie title."))
def open_page(self, parent_window=None, url=None): # dont use base functionality # use the Amazon Web API self.parent_window = parent_window try: accesskey = self.config.get('amazon_accesskey', None, section='extensions') secretkey = self.config.get('amazon_secretkey', None, section='extensions') 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 amazon.setLicense(accesskey, secretkey) locale = self.config.get('amazon_locale', 0, section='extensions') if locale == '1' or locale == 'UK': locale = 'uk' elif locale == '2' or locale == 'DE': locale = 'de' elif locale == '3' or locale == 'CA': locale = 'ca' elif locale == '4' or locale == 'FR': locale = 'fr' elif locale == '5' or locale == 'JP': locale = 'jp' else: locale = None retriever = AmazonRetriever(self.movie_id, locale, parent_window, self.progress, 'Get') retriever.start() while retriever.isAlive(): self.progress.pulse() while gtk.events_pending(): gtk.main_iteration() self.page = retriever.result.Item[0] except: self.page = '' try: log.exception('Error retrieving results from amazon.') log.error(retriever.result.Request.Errors.Error.Message) except: pass return self.page
def add_movie_db(self, close): session = self.db.Session() details = get_details(self) if not details['o_title'] and not details['title']: gutils.error(_("You should fill the original title\nor the movie title."), parent=self.widgets['add']['window']) return False asked = False if details['o_title']: if session.query(db.Movie).filter_by(o_title=details['o_title']).count() > 0: asked = True if not gutils.question(_('Movie with that title already exists, are you sure you want to add?'), self.widgets['add']['window']): return False if not asked and details['title']: if session.query(db.Movie).filter_by(title=details['title']).count() > 0: if not gutils.question(_('Movie with that title already exists, are you sure you want to add?'), self.widgets['add']['window']): return False new_poster_md5 = None if details['image']: tmp_image_path = details['image'] if not os.path.isfile(tmp_image_path): tmp_image_path = os.path.join(self.locations['temp'], "poster_%s.jpg" % details['image']) if os.path.isfile(tmp_image_path): new_poster_md5 = gutils.md5sum(file(tmp_image_path, 'rb')) if session.query(db.Poster).filter_by(md5sum=new_poster_md5).count() == 0: try: data = file(tmp_image_path, 'rb').read() except Exception, e: log.warning("cannot read poster data") else: poster = db.Poster(md5sum=new_poster_md5, data=data) del details["image"] details["poster_md5"] = new_poster_md5 session.add(poster) else: details["poster_md5"] = new_poster_md5 try: if not tmp_image_path == details['image']: os.remove(tmp_image_path) except Exception, e: log.warn("cannot remove temporary file %s", tmp_image_path)
def add_movie_db(self, close): details = get_details(self) if not details['o_title'] and not details['title']: gutils.error(self.widgets['results']['window'], _("You should fill the original title\nor the movie title."), parent=self.widgets['add']['window']) return False if details['o_title']: tmp_movie = self.db.session.query(db.Movie).filter_by(o_title=details['o_title']).first() if tmp_movie is not None: response = gutils.question(_('Movie with that title already exists, are you sure you want to add?'), \ False, self.widgets['add']['window']) if response == gtk.RESPONSE_NO: return False if details['title']: tmp_movie = self.db.session.query(db.Movie).filter_by(title=details['title']).first() if tmp_movie is not None: response = gutils.question(_('Movie with that title already exists, are you sure you want to add?'), \ False, self.widgets['add']['window']) if response == gtk.RESPONSE_NO: return False if details['image']: tmp_image_path = os.path.join(self.locations['temp'], "poster_%s.jpg" % details['image']) if os.path.isfile(tmp_image_path): new_poster_md5 = gutils.md5sum(file(tmp_image_path, 'rb')) poster = self.db.session.query(db.Poster).filter_by(md5sum=new_poster_md5).first() if not poster: try: data = file(tmp_image_path, 'rb').read() except Exception, e: log.warning("cannot read poster data") else: poster = db.Poster(md5sum=new_poster_md5, data=data) del details["image"] details["poster_md5"] = new_poster_md5 self.db.session.add(poster) try: os.remove(tmp_image_path) except Exception, e: log.warn("cannot remove temporary file %s", tmp_image_path)
def open_page(self, parent_window=None, url=None): # dont use base functionality # use the Amazon Web API self.parent_window = parent_window try: accesskey = self.config.get("amazon_accesskey", None, section="extensions") secretkey = self.config.get("amazon_secretkey", None, section="extensions") 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 amazon.setLicense(accesskey, secretkey) locale = self.config.get("amazon_locale", 0, section="extensions") if locale == "1" or locale == "UK": locale = "uk" elif locale == "2" or locale == "DE": locale = "de" elif locale == "3" or locale == "CA": locale = "ca" elif locale == "4" or locale == "FR": locale = "fr" elif locale == "5" or locale == "JP": locale = "jp" else: locale = None retriever = AmazonRetriever(self.movie_id, locale, parent_window, self.progress, "Get") retriever.start() while retriever.isAlive(): self.progress.pulse() while gtk.events_pending(): gtk.main_iteration() self.page = retriever.result.Item[0] except: self.page = "" try: log.exception("Error retrieving results from amazon.") log.error(retriever.result.Request.Errors.Error.Message) except: pass return self.page
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 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 mailto(self, tls, port, server, auth, user, password, sender, to, subject, msg): """ sends an email """ try: session = smtplib.SMTP(server, port) session.set_debuglevel(1) except socket.timeout: gutils.error(_("Connection timed out"), \ self.widgets['window']) return () if tls == True: session.ehlo() session.starttls() session.ehlo() if auth: try: session.login(user, password) except: gutils.error(_("Error sending e-mail: %s")%_("login failure"), \ self.widgets['window']) return headers = "From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n" \ % (sender, to, subject) try: smtpresult = session.sendmail(sender, to, headers + msg) gutils.info(_("E-mail sent successfully"), self.widgets['window']) return except: gutils.error( _("Error sending e-mail: %s") % "", self.widgets['window']) session.quit()
def get_movie(self, parent_window=None): try: # check for internet connection urllib2.urlopen("http://www.griffith.cc") # # initialize the progress dialog once for the following loading process # if self.progress is None: self.progress = Progress(parent_window) self.progress.set_data(parent_window, _("Fetching data"), _("Wait a moment"), True) # # get the page # if not self.open_page(parent_window): return None return True except: self.progress.hide() gutils.error(_("Connection failed.")) return False
def send_email(self): if len(self.person_email): if self.config.get('use_auth', False, section='mail') == True: use_auth = 1 else: use_auth = 0 try: mailto(self, self.config.get('mail_use_tls', False, section='mail'), \ self.config.get('mail_smtp_port', '25', section='mail'), \ self.config.get('smtp_server', 'localhost', section='mail'), \ use_auth, self.config.get('username', '', section='mail'), \ self.config.get('password', '', section='mail'), \ self.config.get('email', 'griffith', section='mail'), self.person_email, \ _("Movie loan reminder"), _("Hi, %s!\n\nJust to remind you that I'm really needing the following movie I have loaned to you recently:\n\n%s (%s)\n\nLoaned on %s") \ %(self.person_name, self.widgets['movie']['o_title'].get_text().decode('utf-8'), \ self.widgets['movie']['title'].get_text().decode('utf-8'), self.loan_date[:10])) except: gutils.error( _("Mail could not be sent. Please check e-mail preferences."), self.widgets['window']) else: gutils.info(_("This person has no e-mail address defined."), \ self.widgets['window'])
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)) else: myiter = self.p_treemodel.insert_after(None, None) self.p_treemodel.set_value(myiter, 0, p.name) self.p_treemodel.set_value(myiter, 1, p.email) self.widgets['people']['window'].present() else: gutils.error(_("You should fill the person name")) def edit_person(self): try: treeselection = self.widgets['people']['treeview'].get_selection() (tmp_model, tmp_iter) = treeselection.get_selected() name = tmp_model.get_value(tmp_iter,0).decode('utf-8') except: return p = self.db.session.query(db.Person).filter_by(name=name).first() if p: self.widgets['person']['e_name'].set_text(p.name) self.widgets['person']['e_email'].set_text(p.email) self.widgets['person']['e_phone'].set_text(p.phone) self.widgets['person']['e_id'].set_text(str(p.person_id)) self.widgets['person']['e_window'].show()
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 run(self): """exports a simple movie list to a pdf file""" basedir = None if not self.config is None: basedir = self.config.get('export_dir', None, section='export-pdf') if basedir is None: filename = gutils.file_chooser( _("Export a PDF"), action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name="griffith_simple_list.pdf") else: filename = gutils.file_chooser( _("Export a PDF"), action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name="griffith_simple_list.pdf", folder=basedir) if filename is not False and filename[0]: if not self.config is None and filename[1]: self.config.set('export_dir', filename[1], section='export-pdf') self.config.save() overwrite = None pdffilename = filename[0].decode('utf-8') if os.path.isfile(pdffilename): if gutils.question( _("File exists. Do you want to overwrite it?"), self.parent_window): overwrite = True else: overwrite = False if overwrite == True or overwrite is None: try: # filename encoding defaultLang, defaultEnc = getdefaultlocale() if defaultEnc is None: defaultEnc = 'UTF-8' c = SimpleDocTemplate(pdffilename.encode(defaultEnc), \ author = 'Griffith', \ title = _('List of films').encode('utf-8'), \ subject = _('List of films').encode('utf-8'), \ allowSplitting = False) # data encoding #if defaultEncoding == 'WinAnsiEncoding': # defaultEnc = 'cp1252' #else: defaultEnc = 'utf-8' pdf_elements = self.config.get( 'pdf_elements', 'image,director,genre,cast').split(',') self.create_styles() style = self.styles["Normal"] Story = [Spacer(1, 2 * inch)] # select sort column - FIXME sort_column_name = self.config.get('sortby', 'number', section='mainlist') sort_reverse = self.config.get('sortby_reverse', False, section='mainlist') do_grouping = True for i in sort_column_name.split(','): if i != 'title' and i != 'o_title': do_grouping = False # build the query query = self.get_query() movies = query.execute().fetchall() # define some custom stylesheetfont total = len(movies) p = Paragraph( saxutils.escape((_("List of films")).encode('utf-8')), self.styles["Heading1"]) Story.append(p) Story.append(Paragraph(" ", style)) p = Paragraph( saxutils.escape((_("Total Movies: %s") % str(total)).encode('utf-8')), self.styles["Heading3"]) Story.append(p) Story.append(Paragraph(" ", style)) # output movies first_letter = '' for movie in movies: number = movie.movies_number if movie.movies_o_title: original_title = movie.movies_o_title.encode( defaultEnc) else: original_title = '' if movie.movies_title: title = movie.movies_title.encode(defaultEnc) else: title = '' grouping_title = movie.movies_title if grouping_title is None: grouping_title = u'None' if movie.movies_director: director = ' - ' + movie.movies_director.encode( defaultEnc) else: director = "" # group by first letter # use movie.title/grouping_title for grouping because of encoding problems !!! if do_grouping and grouping_title[0] != first_letter: if grouping_title[0] in '0123456789': # Group Numbers if first_letter != '0-9': first_letter = '0-9' paragraph_text = saxutils.escape( first_letter) p = Paragraph( paragraph_text.decode(defaultEnc), self.styles['Heading2']) Story.append(p) else: first_letter = grouping_title[0] paragraph_text = saxutils.escape(first_letter) p = Paragraph( paragraph_text.decode(defaultEnc), self.styles['Heading2']) Story.append(p) # add movie title paragraph_text = '<b>'+ saxutils.escape(title) + '</b>' + \ saxutils.escape(' (' + original_title + ') | ' + str(number)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Heading3']) if 'image' in pdf_elements: image_filename = None if movie.movies_poster_md5: image_filename = gutils.get_image_fname( movie.movies_poster_md5, self.db, 'm') if image_filename: p = ParagraphAndImage(p, Image(image_filename, width=30, height=40), side='left') # wrap call needed because of a bug in reportlab flowables.py - ParagraphAndImage::split(self,availWidth, availHeight) # AttributeError: ParagraphAndImage instance has no attribute 'wI' p.wrap(30, 40) Story.append(p) if 'year' in pdf_elements and movie.movies_year: paragraph_text = '<b>' + _( 'Year') + ': </b>' + saxutils.escape( str(movie.movies_year)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'runtime' in pdf_elements and movie.movies_runtime: paragraph_text = '<b>' + _( 'Runtime') + ': </b>' + saxutils.escape( str(movie.movies_runtime)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'genre' in pdf_elements and movie.movies_genre: paragraph_text = '<b>' + _( 'Genre') + ': </b>' + saxutils.escape( movie.movies_genre.encode(defaultEnc)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'director' in pdf_elements and movie.movies_director: paragraph_text = '<i><b>' + _( 'Director') + ': </b>' + saxutils.escape( movie.movies_director.encode( defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'cast' in pdf_elements and movie.movies_cast: paragraph_text = '<i><b>' + _( 'Cast') + ': </b>' + saxutils.escape('; '.join( movie.movies_cast.encode(defaultEnc).split( "\n")[0:2])) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'plot' in pdf_elements and movie.movies_plot: paragraph_text = '<i><b>' + _( 'Plot') + ': </b>' + saxutils.escape( movie.movies_plot.encode( defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'notes' in pdf_elements and movie.movies_notes: paragraph_text = '<i><b>' + _( 'Notes') + ': </b>' + saxutils.escape( movie.movies_notes.encode( defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) resolution = self._get_resolution(movie) if resolution: paragraph_text = '<i><b>' + _( 'Resolution') + ': </b>' + saxutils.escape( resolution.encode(defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if movie.volumes_name: paragraph_text = '<i><b>' + _( 'Volume') + ': </b>' + saxutils.escape( movie.volumes_name.encode( defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if movie.collections_name: paragraph_text = '<i><b>' + _( 'Collection') + ': </b>' + saxutils.escape( movie.collections_name.encode( defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) c.build(Story, onFirstPage=self.page_template, onLaterPages=self.page_template) gutils.info(_('PDF has been created.'), self.parent_window) except Exception, e: log.exception('') gutils.error(str(e))
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 restore(self, merge=False): """ Merge database from: * compressed backup (*.zip) * SQLite2 *.gri file * SQLite3 *.db file """ # let user select a backup file filename, path = gutils.file_chooser(_("Restore Griffith backup"), \ action=gtk.FILE_CHOOSER_ACTION_OPEN, backup=True, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) if not filename: log.debug('no file selected') return False try: tmp_db = None tmp_dir = mkdtemp() os.mkdir(os.path.join(tmp_dir, 'posters')) print filename if filename.lower().endswith('.zip'): try: zip_file = zipfile.ZipFile(filename, 'r') except: gutils.error(_("Can't read backup file"), self.widgets['window']) return False old_config_file = False # unpack files to temporary directory for file_path in zip_file.namelist(): file_name = os.path.split(file_path)[-1] if not os.path.isdir(file_name): if not file_name: log.debug('skipping %s', file_path) continue if 'posters' in file_path: new_file = os.path.join(tmp_dir, 'posters', file_name) else: new_file = os.path.join(tmp_dir, file_name) if file_name.endswith('.conf'): old_config_file = new_file outfile = open(new_file, 'wb') outfile.write(zip_file.read(file_path)) outfile.close() zip_file.close() # restore config file (new one will be created if old config format is detected) tmp_config = config.Config(file=os.path.join(tmp_dir, 'griffith.cfg')) if old_config_file: log.info('Old config file detected. Please note that it will not be used.') f = open(old_config_file, 'r') old_config_raw_data = f.read() f.close() if old_config_raw_data.find('griffith.gri') >= -1: tmp_config.set('file', 'griffith.gri', section='database') # update filename var. to point to the unpacked database filename = os.path.join(tmp_dir, tmp_config.get('name', 'griffith', section='database') + '.db') else: # not a zip file? prepare a fake config file then tmp_config = config.Config(file=os.path.join(tmp_dir, 'griffith.cfg')) tmp_config.set('type', 'sqlite', section='database') tmp_config.set('file', 'griffith.db', section='database') # prepare temporary GriffithSQL instance locations = {'home': tmp_dir} # check if file needs conversion if filename.lower().endswith('.gri'): from dbupgrade import convert_from_old_db tmp_db = convert_from_old_db(tmp_config, filename, os.path.join(tmp_dir, 'griffith.db'), locations) if not tmp_db: log.info("MERGE: Can't convert database, aborting.") return False else: tmp_db = sql.GriffithSQL(tmp_config, tmp_dir, fallback=False) if merge: merge_db(tmp_db, self.db) else: self.db.session.rollback() # cancel all pending operations copy_db(tmp_db.session.bind, self.db.session.bind) # update old database section with current config values # (important while restoring to external databases) for key in ('name', 'passwd', 'host', 'user', 'file', 'type', 'port'): tmp_config.set(key, self.config.get(key, section='database'), section='database') tmp_config._file = self.config._file self.config = tmp_config self.config.save() dictionaries(self) people_treeview(self) # let's refresh the treeview self.clear_details() self.populate_treeview() #gutils.info(_("Databases merged!\n\nProcessed movies: %s\nMerged movies: %s"%(movies, merged)), self.widgets['window']) gutils.info(_("Backup restored"), self.widgets['window']) except: log.exception('') raise finally: # disposing the temporary db connection before rmtree and in finally block to avoid locked db file if tmp_db: tmp_db.dispose() log.debug('temporary directory no logger needed, removing %s', tmp_dir) rmtree(tmp_dir)
def create(self): """perform a compressed griffith database/posters/preferences backup""" #if self.db.session.bind.engine.name != 'sqlite': # gutils.error(_("Backup function is available only for SQLite engine for now"), self.widgets['window']) # return False default_name = "%s_backup_%s.zip" % (self.config.get('name', 'griffith', section='database'),\ datetime.date.isoformat(datetime.datetime.now())) filename = gutils.file_chooser(_("Save Griffith backup"), \ action=gtk.FILE_CHOOSER_ACTION_SAVE, name=default_name, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) if filename and filename[0]: proceed = True zipfilename = filename[0].decode('utf-8') log.debug('Backup filename: %s', zipfilename) if os.path.isfile(zipfilename): if not gutils.question(_("File exists. Do you want to overwrite it?"), window=self.widgets['window']): proceed = False if proceed: try: if zipfile.zlib is not None: log.debug('Creating zip file with compression') mzip = zipfile.ZipFile(zipfilename, 'w', zipfile.ZIP_DEFLATED) else: log.debug('Creating zip file without compression') mzip = zipfile.ZipFile(zipfilename, 'w') except: gutils.error(_("Error creating backup"), self.widgets['window']) return False log.debug('Preparing data and saving it to the zip archive') if self.db.session.bind.engine.name == 'sqlite': mzip.write(os.path.join(self.locations['home'], 'griffith.cfg').encode('utf-8'), arcname='griffith.cfg') db_file_name = "%s.db" % self.config.get('name', 'griffith', section='database') file_path = os.path.join(self.locations['home'], db_file_name).encode('utf-8') mzip.write(file_path, arcname=db_file_name) else: tmp_engine = None try: tmp_dir = mkdtemp() tmp_config_file = os.path.join(tmp_dir, 'griffith.cfg') self.config.save(tmp_config_file) tmp_config = config.Config(file=tmp_config_file) tmp_config.set('type', 'sqlite', section='database') tmp_config.set('file', 'griffith.db', section='database') tmp_config.set('name', 'griffith', section='database') tmp_config.save() mzip.write(tmp_config._file, arcname='griffith.cfg') tmp_file = os.path.join(tmp_dir, 'griffith.db') tmp_engine = create_engine("sqlite:///%s" % tmp_file) db.metadata.create_all(bind=tmp_engine) # SQLite doesn't care about foreign keys much so we can just copy the data for table in db.metadata.sorted_tables: if table.name in ('posters', 'filters'): continue # see below data = table.select(bind=self.db.session.bind).execute().fetchall() if data: table.insert(bind=tmp_engine).execute(data) # posters for poster in db.metadata.tables['posters'].select(bind=self.db.session.bind).execute(): db.metadata.tables['posters'].insert(bind=tmp_engine).execute(md5sum=poster.md5sum, data=StringIO(poster.data).read()) mzip.write(tmp_file, arcname='griffith.db') finally: # disposing the temporary db connection before rmtree and in finally block to avoid locked db file if tmp_engine: tmp_engine.dispose() rmtree(tmp_dir) gutils.info(_("Backup has been created"), self.widgets['window'])