def export_csv(self): basedir = None if not self.persistent_config is None: basedir = self.persistent_config.get('export_dir', None, section='export-csv') if basedir is None: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.csv') else: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.csv',folder=basedir) if filename[0]: if not self.persistent_config is None and filename[1]: self.persistent_config.set('export_dir', filename[1], section='export-csv') self.persistent_config.save() overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, _("File exists. Do you want to overwrite it?"), 1, self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: writer = csv.writer(file(filename[0], 'w'), dialect=csv.excel) for movie in self.db.Movie.select(): t = [] for s in ('number', 'o_title', 'title', 'director', 'year', 'classification', 'country', 'genre', 'rating', 'runtime', 'studio', 'seen', 'loaned', 'o_site', 'site', 'trailer', 'plot', 'cast', 'notes','image'): t.append(movie[s]) writer.writerow(t) gutils.info(self, _("%s file has been created.")%"CSV", self.parent)
def show_dialog(self): # shows a file dialog and sets self.filepath # derived classes which overwrite this method have also to set self.filepath basedir = None if not self.config is None and not self.config_section is None: basedir = self.config.get('export_dir', None, section=self.config_section) if basedir is None: filenames = gutils.file_chooser(_('Export a %s document') % self.export_name, action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name=self.filename) else: filenames = gutils.file_chooser(_('Export a %s document') % self.export_name, action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name=self.filename, folder=basedir) if filenames[0]: self.filepath = filenames[0] if len(filenames) > 1: self.dirpath = filenames[1] else: self.dirpath = os.path.dirname(self.filepath) self.filename = os.path.basename(self.filepath) if not self.config is None and self.dirpath and not self.config_section is None: self.config.set('export_dir', self.dirpath, section=self.config_section) self.config.save() overwrite = None if os.path.isfile(self.filepath): response = gutils.question(_('File exists. Do you want to overwrite it?'), 1, self.parent_window) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: return True return False
def run(self): basedir = None if self.config is not None: basedir = self.config.get('export_dir', None, section='export-csv') if not basedir: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name='griffith_list.csv') else: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE,gtk.RESPONSE_OK), name='griffith_list.csv', folder=basedir) if filename and filename[0]: if self.config is not None and filename[1]: self.config.set('export_dir', filename[1], section='export-csv') self.config.save() overwrite = None if os.path.isfile(filename[0]): if gutils.question(_("File exists. Do you want to overwrite it?"), self.parent_window): overwrite = True else: overwrite = False if overwrite or overwrite is None: movies = self.get_query().execute() writer = csv.writer(file(filename[0], 'w'), dialect=csv.excel) # write column header row writer.writerow(self.fields_to_export) # write data rows for movie in movies: t = [] for s in self.exported_columns: t.append(movie[s]) writer.writerow(t) gutils.info(_("%s file has been created.") % "CSV", self.parent_window)
def run(self): basedir = None if self.config is not None: basedir = self.config.get('export_dir', None, section='export-xml') if basedir is None: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml') else: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml',folder=basedir) if filename and filename[0]: if self.config is not None and filename[1]: self.config.set('export_dir', filename[1], section='export-xml') self.config.save() overwrite = None if os.path.isfile(filename[0]): response = gutils.question(_("File exists. Do you want to overwrite it?"), True, self.parent_window) if response==-8: overwrite = True else: overwrite = False if overwrite or overwrite is None: # create document impl = xml.dom.minidom.getDOMImplementation() doc = impl.createDocument(None, "root", None) root = doc.documentElement movies = self.get_query().execute().fetchall() # create object for movie in movies: e = doc.createElement('movie') root.appendChild(e) for key in self.exported_columns: e2 = doc.createElement(str(key).replace('movies_', '')) if movie[key] is None: value = '' elif movie[key] in (True, False): value = str(int(movie[key])) else: if movie[key] is unicode: value = movie[key].encode('utf-8') else: value = str(movie[key]) t = doc.createTextNode(value) e2.appendChild(t) e.appendChild(e2) # write XML to file fp = open(filename[0], "w") xml.dom.ext.PrettyPrint(doc, fp) fp.close() gutils.info( _("%s file has been created.")%"XML", self.parent_window)
def export_xml(self): basedir = None if not self.persistent_config is None: basedir = self.persistent_config.get('export_dir', None, section='export-xml') if basedir is None: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml') else: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml',folder=basedir) if filename[0]: if not self.persistent_config is None and filename[1]: self.persistent_config.set('export_dir', filename[1], section='export-xml') self.persistent_config.save() overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, _("File exists. Do you want to overwrite it?"), 1, self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: # create document impl = xml.dom.minidom.getDOMImplementation() doc = impl.createDocument(None, "root", None) root = doc.documentElement # create object for movie in self.db.Movie.select(): e = doc.createElement('movie') root.appendChild(e) for key in movie.c.keys(): e2 = doc.createElement(key) if movie[key] is None: value = '' elif movie[key] in (True, False): value = str(int(movie[key])) else: value = str(movie[key]) t = doc.createTextNode(value) e2.appendChild(t) e.appendChild(e2) # write XML to file fp = open(filename[0], "w") xml.dom.ext.PrettyPrint(doc, fp) fp.close() gutils.info(self, _("%s file has been created.")%"XML", self.parent)
def cover_image(self,number): 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)) if filename[0]: cover_image_process(self, filename[0], number)
def cover_image(self, number): 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)) if filename[0]: cover_image_process(self, filename[0], number)
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 export_xml(self): filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml') if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, _("File exists. Do you want to overwrite it?"), 1, self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite == None: # create document impl = xml.dom.minidom.getDOMImplementation() doc = impl.createDocument(None, "root", None) root = doc.documentElement # create object data = self.db.get_all_data(order_by="number ASC") for row in data: e = doc.createElement('movie') root.appendChild(e) for key,value in row.items(): e2 = doc.createElement(key) t = doc.createTextNode(str(value)) e2.appendChild(t) e.appendChild(e2) # write XML to file fp = open(filename[0], "w") xml.dom.ext.PrettyPrint(doc, fp) fp.close() gutils.info(self, _("%s file has been created.")%"XML", self.parent)
def run(self): tmp_dir = mkdtemp() griffith_list = open(os.path.join(tmp_dir, "movies"), "w") t = [] movies = self.get_query().execute().fetchall() for movie in movies: t.append( "%s | %s | %s | %s" % ( movie["number"], movie["o_title"].encode("utf-8"), movie["title"].encode("utf-8"), movie["director"].encode("utf-8"), ) ) griffith_list.write("<title>%s</title><br><br>" % _("My Movies List")) for movie in t: griffith_list.write(movie) griffith_list.write("<br>") griffith_list.close() # this is a mac, lets export to iPod's notes folder # TODO: windows and linux iPod autodetection if platform.system() == "Darwin": thisPod = Path2iPod() thisPath = thisPod.returnPath() if thisPath: commands.getoutput( "mv " + os.path.join(tmp_dir, "movies") + ' "' + thisPath + '/Notes/"' ) # FIXME: WTF? gutils.info(_("List was successful exported to iPod."), self.parent_window) else: gutils.info(_("iPod is not connected."), self.parent_window) # this is not a mac, lets save the file else: filename = gutils.file_chooser( _("Export a %s document") % "CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name="ipod_griffith_list", ) if filename and filename[0]: overwrite = None if os.path.isfile(filename[0]): 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: shutil.copyfile(os.path.join(tmp_dir, "movies"), filename[0]) gutils.info( _("List was successful exported. Now you should move it to the 'Notes' folder on your iPod."), self.parent_window, )
def export_simple_pdf(self): """exports a simple movie list to a pdf file""" myconfig = config.Config() if myconfig.get('font', '')!='': self.fontName = "custom_font" pdfmetrics.registerFont(TTFont(self.fontName, myconfig.get('font', ''))) else: self.fontName = "Helvetica" 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") if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self,_("File exists. Do you want to overwrite it?"),1,self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite == None: c = SimpleDocTemplate(filename[0]) style = self.styles["Normal"] Story = [Spacer(1,2*inch)] # define some custom stylesheetfont total = self.db.count_records('movies') p = Paragraph("<font name='" + self.fontName +"' size=\"18\">" + saxutils.escape((_("List of films")).encode('utf-8')) + '</font>', self.styles["Heading1"] ) Story.append(p) Story.append(Paragraph(" ",style)) p = Paragraph("<font name='" + self.fontName +"' size=\"10\">" + saxutils.escape((_("Total Movies: %s") % str(total)).encode('utf-8')) + '</font>', self.styles["Heading3"]) Story.append(p) Story.append(Paragraph(" ",style)) data = self.db.get_all_data(order_by="number ASC") for row in data: number = str(row['number']) number = number.encode('utf-8') original_title = str(row['original_title']) original_title = original_title.encode('utf-8') title = str(row['title']) title = title.encode('utf-8') if row['year']: year = ' - ' + str(row['year']) else: year = "" year = year.encode('utf-8') if row['director']: director = ' - ' + str(row['director']) else: director = "" director = director.encode('utf-8') p = Paragraph("<font name=" + self.fontName + " size=\"7\">" + \ saxutils.escape(number + " | " + original_title) + \ "</font><font name=" + self.fontName + " size=\"7\">" + \ saxutils.escape(" (" + title + ")" + year + director) + \ "</font>", self.styles["Normal"]) Story.append(p) c.build(Story, onFirstPage=self.page_template, onLaterPages=self.page_template) gutils.info(self, _("PDF has been created."), self.parent)
def run(self): tmp_dir = mkdtemp() griffith_list = open(os.path.join(tmp_dir, "movies"), "w") t = [] def checkForNoneAndEncode(val): if val is None: return '' return val.encode('utf-8') movies = self.get_query().execute().fetchall() for movie in movies: t.append("%s | %s | %s | %s" % (movie['number'], \ checkForNoneAndEncode(movie['o_title']), checkForNoneAndEncode(movie['title']), checkForNoneAndEncode(movie['director']))) griffith_list.write("<title>%s</title><br><br>" % _("My Movies List")) for movie in t: griffith_list.write(movie) griffith_list.write("<br>") griffith_list.close() # this is a mac, lets export to iPod's notes folder # TODO: windows and linux iPod autodetection if platform.system() == 'Darwin': thisPod = Path2iPod() thisPath = thisPod.returnPath() if thisPath: commands.getoutput('mv ' + os.path.join(tmp_dir, "movies") + ' "' + thisPath + '/Notes/"') # FIXME: WTF? gutils.info(_("List successfully exported to iPod."), self.parent_window) else: gutils.info(_("iPod is not connected."), self.parent_window) # this is not a mac, lets save the file else: filename = gutils.file_chooser(_("Export a %s document")%"iPod", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='ipod_griffith_list') if filename and filename[0]: overwrite = None if os.path.isfile(filename[0]): 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: shutil.copyfile(os.path.join(tmp_dir, "movies"), filename[0]) gutils.info( _("The list was successfully exported. Now you should move it to the 'Notes' folder on your iPod." ), self.parent_window)
def export_simple_pdf(self): """exports a simple movie list to a pdf file""" myconfig = config.Config(os.path.join(self.locations['home'], 'griffith.conf')) if myconfig.get('font', '')!='': self.fontName = "custom_font" pdfmetrics.registerFont(TTFont(self.fontName, myconfig.get('font', ''))) else: self.fontName = "Helvetica" 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") if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self,_("File exists. Do you want to overwrite it?"),1,self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: c = SimpleDocTemplate(filename[0]) style = self.styles["Normal"] Story = [Spacer(1,2*inch)] # define some custom stylesheetfont total = self.db.Movie.count() p = Paragraph("<font name='" + self.fontName +"' size=\"18\">" + saxutils.escape((_("List of films")).encode('utf-8')) + '</font>', self.styles["Heading1"] ) Story.append(p) Story.append(Paragraph(" ",style)) p = Paragraph("<font name='" + self.fontName +"' size=\"10\">" + saxutils.escape((_("Total Movies: %s") % str(total)).encode('utf-8')) + '</font>', self.styles["Heading3"]) Story.append(p) Story.append(Paragraph(" ",style)) movies = self.db.Movie.select() for movie in movies: number = movie.number original_title = str(movie.o_title) title = str(movie.title) if movie.year: year = ' - ' + str(movie.year) else: year = "" if movie.director: director = ' - ' + str(movie.director) else: director = "" p = Paragraph("<font name=" + self.fontName + " size=\"7\">" + \ saxutils.escape(str(number) + " | " + original_title) + \ "</font><font name=" + self.fontName + " size=\"7\">" + \ saxutils.escape(" (" + title + ")" + year + director) + \ "</font>", self.styles["Normal"]) Story.append(p) c.build(Story, onFirstPage=self.page_template, onLaterPages=self.page_template) gutils.info(self, _("PDF has been created."), self.parent)
def run(self): basedir = None if self.config is not None: basedir = self.config.get('export_dir', None, section='export-csv') if not basedir: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name='griffith_list.csv') else: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE,gtk.RESPONSE_OK), name='griffith_list.csv', folder=basedir) if filename and filename[0]: if self.config is not None and filename[1]: self.config.set('export_dir', filename[1], section='export-csv') self.config.save() overwrite = None if os.path.isfile(filename[0]): if gutils.question( _("File exists. Do you want to overwrite it?"), self.parent_window): overwrite = True else: overwrite = False if overwrite or overwrite is None: movies = self.get_query().execute() writer = csv.writer(file(filename[0], 'w'), dialect=csv.excel) # write column header row writer.writerow(self.fields_to_export) # write data rows for movie in movies: t = [] for s in self.exported_columns: t.append(movie[s]) writer.writerow(t) gutils.info( _("%s file has been created.") % "CSV", self.parent_window)
def show_dialog(self): # shows a file dialog and sets self.filepath # derived classes which overwrite this method have also to set self.filepath basedir = None if not self.config is None and not self.config_section is None: basedir = self.config.get('export_dir', None, section=self.config_section) if basedir is None: filenames = gutils.file_chooser(_('Export a %s document') % self.export_name, action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name=self.filename) else: filenames = gutils.file_chooser(_('Export a %s document') % self.export_name, action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name=self.filename, folder=basedir) if filenames[0]: self.filepath = filenames[0] if len(filenames) > 1: self.dirpath = filenames[1] else: self.dirpath = os.path.dirname(self.filepath) self.filename = os.path.basename(self.filepath) if not self.config is None and self.dirpath and not self.config_section is None: self.config.set('export_dir', self.dirpath, section=self.config_section) self.config.save() overwrite = None if os.path.isfile(self.filepath): 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: return True return False
def change_poster_select_file(self, number, handler=update_image): 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") if handler: return handler(self, number, filename) return False
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 change_poster_select_file(self, number, handler=update_image): 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') if handler: return handler(self, number, filename) return False
def export_iPod(self): tmp_dir = mkdtemp() griffith_list = open(os.path.join(tmp_dir,"movies"),"w") t = [] for movie in self.db.Movie.all(): t.append("%s | %s | %s | %s"%(movie['number'],movie['o_title'],movie['title'],movie['director'])) griffith_list.write("<title>%s</title><br><br>"%_("My Movies List")) for movie in t: griffith_list.write(str(movie)) griffith_list.write("<br>") griffith_list.close() # this is a mac, lets export to iPod's notes folder # TODO: windows and linux iPod autodetection if platform.system() == 'Darwin': thisPod=Path2iPod() thisPath=thisPod.returnPath() if thisPath: commands.getoutput('mv '+os.path.join(tmp_dir,"movies")+' "'+thisPath+'/Notes/"') gutils.info(self, _("List was successful exported to iPod."), self.parent) else: gutils.info(self, _("iPod is not connected."), self.parent) # this is not a mac, lets save the file else: filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='ipod_griffith_list') if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, _("File exists. Do you want to overwrite it?"), 1, self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: shutil.copyfile(os.path.join(tmp_dir,"movies"), filename[0]) gutils.info(self, _("List was successful exported. Now you should move it to the 'Notes' folder on your iPod."), self.parent)
def change_poster(self): """ changes movie poster image to a custom one showing a file chooser dialog to select it """ import shutil picture = self.e_picture m_id = self.get_maintree_selection() 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[0]: try: picture.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(filename[0]).scale_simple(100, 140, gtk.gdk.INTERP_BILINEAR)) file_to_copy = os.path.basename(filename[0]) shutil.copyfile(filename[0],'%s/posters/%s.jpg' % (self.griffith_dir, os.path.splitext(file_to_copy)[0])) gutils.make_thumbnail(self, '%s.jpg' % os.path.splitext(file_to_copy)[0]) gutils.make_medium_image(self, '%s.jpg' % os.path.splitext(file_to_copy)[0]) update.update_image(self, os.path.splitext(file_to_copy)[0], m_id[0]) update_tree_thumbnail(self, '%s/posters/t_%s.jpg' % (self.griffith_dir, os.path.splitext(file_to_copy)[0])) except: gutils.error(self, _("Image not valid."), self.main_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]: response_unzip = gutils.restore(filename[0], self.griffith_dir) if not response_unzip: gutils.error(self, _("Can't read backup file"), self.main_window) return self.db.con.close() self.db = sql.GriffithSQL(self.config, self.debug, self.griffith_dir) from initialize import dictionaries dictionaries(self) gutils.info(self, _("Backup restored"), self.main_window) # let's refresh the treeview self.populate_treeview(self.db.get_all_data()) self.total = self.db.count_records("movies") self.select_last_row(self.total) self.treeview_clicked() self.count_statusbar()
def export_csv(self): filename = gutils.file_chooser(_("Export a %s document")%"CSV", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.csv') if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, _("File exists. Do you want to overwrite it?"), 1, self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite == None: writer = csv.writer(file(filename[0], "w"), dialect=csv.excel) data = self.db.get_all_data(order_by="number ASC") for row in data: t = [] for s in row: try: t.append(s.encode('latin-1')) except: t.append(s) writer.writerow(t) gutils.info(self, _("%s file has been created.")%"CSV", self.parent)
def backup(self): """perform a compressed griffith database/posters/preferences backup""" filename = gutils.file_chooser(_("Save Griffith backup"), \ action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons= \ (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK), \ name='griffith_backup.zip') if filename[0]: overwrite = None if os.path.isfile(filename[0]): response = \ gutils.question(self, \ _("File exists. Do you want to overwrite it?"), \ 1, self.main_window) if response == -8: overwrite = True else: overwrite = False if overwrite == True or overwrite == None: response_zip = gutils.backup(self.griffith_dir, filename[0]) if not response_zip: gutils.error(self, _("Error creating backup"), self.main_window) else: gutils.info(self, _("Backup has been created"), self.main_window)
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))
def export_simple_pdf(self): """exports a simple movie list to a pdf file""" if self.config.get('font', '') != '': self.fontName = 'custom_font' pdfmetrics.registerFont(TTFont(self.fontName, self.config.get('font', ''))) else: self.fontName = "Helvetica" 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[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): response = gutils.question(self,_("File exists. Do you want to overwrite it?"),1,self.parent) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: # filename encoding defaultLang, defaultEnc = getdefaultlocale() if defaultEnc is None: defaultEnc = 'UTF-8' c = SimpleDocTemplate(pdffilename.encode(defaultEnc)) # data encoding if defaultEncoding == 'WinAnsiEncoding': defaultEnc = 'cp1252' else: defaultEnc = 'utf-8' style = self.styles["Normal"] Story = [Spacer(1,2*inch)] # define some custom stylesheetfont total = self.db.Movie.count() p = Paragraph("<font name='" + self.fontName +"' size=\"18\">" + saxutils.escape((_("List of films")).encode('utf-8')) + '</font>', self.styles["Heading1"] ) Story.append(p) Story.append(Paragraph(" ",style)) p = Paragraph("<font name='" + self.fontName +"' size=\"10\">" + saxutils.escape((_("Total Movies: %s") % str(total)).encode('utf-8')) + '</font>', self.styles["Heading3"]) Story.append(p) Story.append(Paragraph(" ",style)) movies = Select(self.db.Movie.c) # select sort column sort_column_name = self.config.get('sortby', 'number', section='mainlist') sort_reverse = self.config.get('sortby_reverse', False, section='mainlist') for i in sort_column_name.split(','): if self.db.Movie.c.has_key(i): if sort_reverse: movies.order_by_clause.append(desc(self.db.Movie.c[i])) else: movies.order_by_clause.append(self.db.Movie.c[i]) movies = movies.execute().fetchall() first_letter = '0' for movie in movies: number = movie.number original_title = str(movie.o_title).encode(defaultEnc) title = str(movie.title).encode(defaultEnc) if movie.director: director = ' - ' + str(movie.director).encode(defaultEnc) else: director = "" # group by first letter if title[0] != first_letter: first_letter = title[0] paragraph_text = '<font name=' + self.fontName + ' size="15">' + saxutils.escape(first_letter) + '</fonts>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Heading2']) Story.append(p) # add movie title paragraph_text = '<font name=' + self.fontName + ' size="7">' + \ '<b>'+ saxutils.escape(title) + '</b>' + \ saxutils.escape(' (' + original_title + '), ' + director + ' | ' + str(number)) + \ '</font>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if not movie.genre is None: paragraph_text = '<font name=' + self.fontName + ' size="5">' + \ '<b>' + _('Genre') + ': </b>' + saxutils.escape(str(movie.genre).encode(defaultEnc)) + \ '</font>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if not movie.cast is None: paragraph_text = '<i><font name=' + self.fontName + ' size="5">' + \ '<b>' + _('Cast') + ': </b>' + saxutils.escape('; '.join(str(movie.cast).encode(defaultEnc).split("\n")[0:2])) + \ '</font></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(self, _('PDF has been created.'), self.parent)
def restore(self, merge=False): """ Merge database from: * compressed backup (*.zip) * SQLite2 *.gri file * SQLite3 *.db file """ # let user select a backup file filename = 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 backup(self): """perform a compressed griffith database/posters/preferences backup""" filename = gutils.file_chooser(_("Save Griffith backup"), \ action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons= \ (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK), \ name='griffith_backup.zip') if filename and filename[0]: overwrite = None if os.path.isfile(filename[0]): response = gutils.question(self, \ _("File exists. Do you want to overwrite it?"), \ 1, self.widgets['window']) if response == -8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: try: mzip = zipfile.ZipFile(filename[0], 'w') except: gutils.error(self, _("Error creating backup"), self.widgets['window']) return False mzip.write(os.path.join(self.locations['home'],'griffith.cfg')) if self.db.metadata.engine.name == 'sqlite': mzip.write(os.path.join(self.locations['home'], self.config.get('file','griffith.db', section='database'))) else: gutils.error(self, _("Backup function is available only for SQLite engine for now"), self.widgets['window']) return False from tempfile import mkdtemp from shutil import rmtree, move from sqlalchemy import BoundMetaData import copy # if backup_to_sqlite: tmp_dir = mkdtemp() tmp_config = copy.deepcopy(self.config) tmp_config._file = os.path.join(tmp_dir,'griffith.cfg') tmp_config.get('type', 'sqlite', section='database') == 'sqlite' tmp_config.set('file', section='database') == "griffith.db" tmp_config.save() # tmp_db = sql.GriffithSQL(tmp_config, self.debug, tmp_dir) # for i in self.db.metadata.tables # tmp_db. tmp_file = os.path.join(tmp_dir, tmp_config.get('file', 'griffith.db', section='database')) tmp_metadata = BoundMetaData("sqlite:///%s" % tmp_file) tmp_metadata.tables = self.db.metadata.tables tmp_metadata.create_all() # for table in self.db.metadata.tables.keys(): for table in [t.name for t in self.db.metadata.table_iterator()]: # table_iterator() will return tables in *correct* order data = self.db.metadata.tables[table].select().execute().fetchall() tmp_metadata.tables[table].insert().execute(data) # for item in data: # tmp_metadata.tables[table].insert().execute(item) tmp_metadata.engine.commit() mzip.write(tmp_file) rmtree(tmp_dir) posters_dir = os.path.join(self.locations['posters']) for movie in self.db.Movie.select(): if movie.image is not None: filename = str(movie.image)+".jpg" filename = os.path.join(posters_dir, filename.encode('utf-8')) if os.path.isfile(filename): try: mzip.write(filename) except: self.debug.show("Can't compress %s" % filename) mzip.close() gutils.info(self, _("Backup has been created"), self.widgets['window'])
def merge(self): # FIXME """ Merge database from: * compressed backup * SQLite2 *.gri file * SQLite3 *.db file """ 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))[0] if filename: from tempfile import mkdtemp from shutil import rmtree, move #tmp_config={} #tmp_config.get('type', 'sqlite', section='database') if filename.lower().endswith('.zip'): tmp_dir = mkdtemp() try: zip = zipfile.ZipFile(filename, 'r') except: gutils.error(self, _("Can't read backup file"), self.widgets['window']) return False for each in zip.namelist(): file_to_restore = os.path.split(each) if not os.path.isdir(file_to_restore[1]): myfile = os.path.join(tmp_dir, file_to_restore[1]) outfile = open(myfile, 'wb') outfile.write(zip.read(each)) outfile.flush() outfile.close() # load stored database filename tmp_config = config.Config(file=os.path.join(tmp_dir,'griffith.conf')) filename = os.path.join(tmp_dir, tmp_config('file', 'griffith.db', section='database')) zip.close() # check if file needs conversion if filename.lower().endswith(".gri"): if os.path.isfile(filename) and open(filename).readline()[:47] == "** This file contains an SQLite 2.1 database **": self.debug.show("MERGE: SQLite2 database format detected. Converting...") if not self.db.convert_from_sqlite2(filename, os.path.join(tmp_dir, self.config.get('file', 'griffith.db', section='database'))): self.debug.show("MERGE: Can't convert database, aborting.") return False tmp_dir, tmp_file = os.path.split(filename) self.config.get('file', tmp_file, section='database') tmp_db = sql.GriffithSQL(tmp_config, self.debug, tmp_dir) merged=0 movies = tmp_db.Movie.count() for movie in tmp_db.Movie.select(): if self.db.Movie.get_by(o_title=movie.o_title) is not None: continue t_movies = {} for column in movie.mapper.c.keys(): t_movies[column] = eval("movie.%s"%column) # replace number with new one t_movies["number"] = gutils.find_next_available(self.db) # don't restore volume/collection/tag/language/loan data (it's dangerous) t_movies.pop('movie_id') t_movies.pop('loaned') t_movies.pop('volume_id') t_movies.pop('collection_id') if self.db.add_movie(t_movies): print t_movies if movie.image is not None: dest_file = os.path.join(self.locations['posters'], movie.image+'.jpg') if not os.path.isfile(dest_file): src_file = os.path.join(tmp_dir, movie.image+'.jpg') if os.path.isfile(src_file): move(src_file, dest_file) merged+=1 rmtree(tmp_dir) from initialize import dictionaries, people_treeview dictionaries(self) people_treeview(self) # let's refresh the treeview self.clear_details() self.populate_treeview(self.db.Movie.select()) self.total = self.db.Movie.count() self.count_statusbar()
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'])
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 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: # 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')) # 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.number if movie.o_title: original_title = movie.o_title.encode(defaultEnc) else: original_title = '' if movie.title: title = movie.title.encode(defaultEnc) else: title = '' grouping_title = movie.title if grouping_title is None: grouping_title = u'None' if movie.director: director = ' - ' + movie.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.poster_md5: image_filename = gutils.get_image_fname(movie.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.year: paragraph_text = '<b>' + _('Year') + ': </b>' + saxutils.escape(str(movie.year)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'runtime' in pdf_elements and movie.runtime: paragraph_text = '<b>' + _('Runtime') + ': </b>' + saxutils.escape(str(movie.runtime)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'genre' in pdf_elements and movie.genre: paragraph_text = '<b>' + _('Genre') + ': </b>' + saxutils.escape(movie.genre.encode(defaultEnc)) p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'director' in pdf_elements and movie.director: paragraph_text = '<i><b>' + _('Director') + ': </b>' + saxutils.escape(movie.director.encode(defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'cast' in pdf_elements and movie.cast: paragraph_text = '<i><b>' + _('Cast') + ': </b>' + saxutils.escape('; '.join(movie.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.plot: paragraph_text = '<i><b>' + _('Plot') + ': </b>' + saxutils.escape(movie.plot.encode(defaultEnc)) + '</i>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if 'notes' in pdf_elements and movie.notes: paragraph_text = '<i><b>' + _('Notes') + ': </b>' + saxutils.escape(movie.notes.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)
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))
def run(self): basedir = None if self.config is not None: basedir = self.config.get("export_dir", None, section="export-xml") if basedir is None: filename = gutils.file_chooser( _("Export a %s document") % "XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name="griffith_list.xml", ) else: filename = gutils.file_chooser( _("Export a %s document") % "XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK), name="griffith_list.xml", folder=basedir, ) if filename and filename[0]: if self.config is not None and filename[1]: self.config.set("export_dir", filename[1], section="export-xml") self.config.save() overwrite = None if os.path.isfile(filename[0]): if gutils.question(_("File exists. Do you want to overwrite it?"), self.parent_window): overwrite = True else: overwrite = False posterdir = os.path.join(os.path.dirname(filename[0]), "posters") if not os.path.exists(posterdir): os.mkdir(posterdir) if overwrite or overwrite is None: # create document impl = xml.dom.minidom.getDOMImplementation() doc = impl.createDocument(None, "root", None) root = doc.documentElement movies = self.get_query().execute().fetchall() # create object for movie in movies: e = doc.createElement("movie") root.appendChild(e) for key in self.exported_columns: e2 = doc.createElement(str(key).replace("movies_", "")) if movie[key] is None: value = "" elif movie[key] in (True, False): value = str(int(movie[key])) else: if movie[key] is unicode: value = movie[key].encode("utf-8") else: value = str(movie[key]) t = doc.createTextNode(value) e2.appendChild(t) e.appendChild(e2) # create image file in ./posters/... md5sum = None posterfilepath = "" if "poster_md5" in self.exported_columns and movie["poster_md5"]: md5sum = movie["poster_md5"] if "movies_poster_md5" in self.exported_columns and movie["movies_poster_md5"]: md5sum = movie["movies_poster_md5"] if md5sum: if gutils.create_imagefile(posterdir, md5sum, self.db): posterfilepath = os.path.join(".", "posters", md5sum + ".jpg") e2 = doc.createElement("image") # relative path to image related to xml file t = doc.createTextNode(posterfilepath) e2.appendChild(t) e.appendChild(e2) # write XML to file xmldata = doc.toprettyxml(encoding="utf-8") fp = open(filename[0], "w") try: fp.write(xmldata) finally: fp.close() gutils.info(_("%s file has been created.") % "XML", self.parent_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']) old_config_file = False 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]) if file_to_restore[1].endswith('.conf'): old_config_file = myfile 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.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: self.config.set('file', 'griffith.gri', section='database') filename = os.path.join(self.locations['home'], self.config.get('name', 'griffith', section='database') + '.db') self.db.session.bind.engine.dispose() # close DB # check if file needs conversion if self.config.get('file', 'griffith.db', section='database').lower().endswith('.gri'): log.info('Old database format detected. Converting...') from dbupgrade import convert_from_old_db if convert_from_old_db(self, filename, os.path.join(self.locations['home'], 'griffith.db')): self.config.save() else: log.error('Cant convert old database, exiting.') import sys sys.exit(4) self.db = sql.GriffithSQL(self.config, self.locations['home'], self.locations) from initialize import dictionaries, people_treeview dictionaries(self) people_treeview(self) # let's refresh the treeview self.clear_details() self.populate_treeview() gutils.info(_("Backup restored"), self.widgets['window'])
def run(self): """exports a simple movie list to a pdf file""" if self.config.get('font', '') != '': self.fontName = 'custom_font' pdfmetrics.registerFont(TTFont(self.fontName, self.config.get('font', ''))) else: self.fontName = "Helvetica" 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): response = gutils.question(_("File exists. Do you want to overwrite it?"), True, self.parent_window) if response==-8: overwrite = True else: overwrite = False if overwrite == True or overwrite is None: # filename encoding defaultLang, defaultEnc = getdefaultlocale() if defaultEnc is None: defaultEnc = 'UTF-8' c = SimpleDocTemplate(pdffilename.encode(defaultEnc)) # data encoding #if defaultEncoding == 'WinAnsiEncoding': # defaultEnc = 'cp1252' #else: defaultEnc = 'utf-8' 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("<font name='" + self.fontName +"' size=\"18\">" + saxutils.escape((_("List of films")).encode('utf-8')) + '</font>', self.styles["Heading1"] ) Story.append(p) Story.append(Paragraph(" ",style)) p = Paragraph("<font name='" + self.fontName +"' size=\"10\">" + saxutils.escape((_("Total Movies: %s") % str(total)).encode('utf-8')) + '</font>', self.styles["Heading3"]) Story.append(p) Story.append(Paragraph(" ",style)) # output movies first_letter = '' for movie in movies: number = movie.number if movie.o_title: original_title = movie.o_title.encode(defaultEnc) else: original_title = '' if movie.title: title = movie.title.encode(defaultEnc) else: title = '' grouping_title = movie.title if grouping_title is None: grouping_title = u'None' if movie.director: director = ' - ' + movie.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 = '<font name=' + self.fontName + ' size="15">' + saxutils.escape(first_letter) + '</fonts>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Heading2']) Story.append(p) else: first_letter = grouping_title[0] paragraph_text = '<font name=' + self.fontName + ' size="15">' + saxutils.escape(first_letter) + '</fonts>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Heading2']) Story.append(p) # add movie title paragraph_text = '<font name=' + self.fontName + ' size="7">' + \ '<b>'+ saxutils.escape(title) + '</b>' + \ saxutils.escape(' (' + original_title + '), ' + director + ' | ' + str(number)) + \ '</font>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if movie.genre is not None: paragraph_text = '<font name=' + self.fontName + ' size="5">' + \ '<b>' + _('Genre') + ': </b>' + saxutils.escape(movie.genre.encode(defaultEnc)) + \ '</font>' p = Paragraph(paragraph_text.decode(defaultEnc), self.styles['Normal']) Story.append(p) if movie.cast is not None: paragraph_text = '<i><font name=' + self.fontName + ' size="5">' + \ '<b>' + _('Cast') + ': </b>' + saxutils.escape('; '.join(movie.cast.encode(defaultEnc).split("\n")[0:2])) + \ '</font></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)
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: try: tmp_dir = mkdtemp() tmp_config = copy.deepcopy(self.config) tmp_config._file = os.path.join(tmp_dir, 'griffith.cfg') 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 tmp_engine.dispose() rmtree(tmp_dir) gutils.info(_("Backup has been created"), self.widgets['window'])
def run(self): basedir = None if self.config is not None: basedir = self.config.get('export_dir', None, section='export-xml') if basedir is None: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml') else: filename = gutils.file_chooser(_("Export a %s document")%"XML", action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK),name='griffith_list.xml',folder=basedir) if filename and filename[0]: if self.config is not None and filename[1]: self.config.set('export_dir', filename[1], section='export-xml') self.config.save() overwrite = None if os.path.isfile(filename[0]): if gutils.question( _("File exists. Do you want to overwrite it?"), self.parent_window): overwrite = True else: overwrite = False posterdir = os.path.join(os.path.dirname(filename[0]), 'posters') if not os.path.exists(posterdir): os.mkdir(posterdir) if overwrite or overwrite is None: # create document impl = xml.dom.minidom.getDOMImplementation() doc = impl.createDocument(None, "root", None) root = doc.documentElement movies = self.get_query().execute().fetchall() # create object for movie in movies: e = doc.createElement('movie') root.appendChild(e) for key in self.exported_columns: e2 = doc.createElement(str(key).replace('movies_', '')) if movie[key] is None: value = '' elif movie[key] in (True, False): value = str(int(movie[key])) else: if movie[key] is unicode: value = movie[key].encode('utf-8') else: value = str(movie[key]) t = doc.createTextNode(value) e2.appendChild(t) e.appendChild(e2) # create image file in ./posters/... md5sum = None posterfilepath = '' if 'poster_md5' in self.exported_columns and movie[ 'poster_md5']: md5sum = movie['poster_md5'] if 'movies_poster_md5' in self.exported_columns and movie[ 'movies_poster_md5']: md5sum = movie['movies_poster_md5'] if md5sum: if gutils.create_imagefile(posterdir, md5sum, self.db): posterfilepath = os.path.join( '.', 'posters', md5sum + '.jpg') e2 = doc.createElement('image') # relative path to image related to xml file t = doc.createTextNode(posterfilepath) e2.appendChild(t) e.appendChild(e2) # write XML to file xmldata = doc.toprettyxml(encoding='utf-8') fp = open(filename[0], "w") try: fp.write(xmldata) finally: fp.close() gutils.info( _("%s file has been created.") % "XML", self.parent_window)