Пример #1
0
	def new_db(self, parent): #{{{
		"""initializes a new griffith database file"""
		response = gutils.question(self, \
			_("Are you sure you want to create a new database?\nYou will lose ALL your current data!"), \
			1, parent.main_window)
		if response == gtk.RESPONSE_YES:
			response_sec = gutils.question(self, \
				_("Last chance!\nDo you confirm that you want\nto lose your current data?"), \
				1, parent.main_window)
			if response_sec == gtk.RESPONSE_YES:
				# delete images
				for root, dirs, files in os.walk(os.path.join(self.griffith_dir,"posters"), topdown=False):
					for name in files:
						os.remove(os.path.join(root, name))
				# delete db
				parent.db.con.close()
				os.unlink(os.path.join(self.griffith_dir,self.config.get('default_db')))
				# create/connect db
				parent.db = GriffithSQL(self.config, self.debug, self.griffith_dir)
				parent.clear_details()
				parent.total = 0
				parent.count_statusbar()
				parent.treemodel.clear()
				from initialize	import dictionaries
				dictionaries(parent)
			else:
				pass
		else:
			pass
Пример #2
0
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)
Пример #3
0
def delete_poster(self):
    session = self.db.Session()
    movie = session.query(db.Movie).filter_by(movie_id=self._movie_id).first()
    if not movie:
        log.error("Cannot delete unknown movie's poster!")
        return False
    response = gutils.question(_("Are you sure you want to delete this poster?"), True, self.widgets["window"])
    if response == -8:
        image_path = os.path.join(self.locations["images"], "default.png")
        handler = self.widgets["movie"]["picture"].set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(image_path))
        gutils.garbage(handler)
        update_tree_thumbnail(self, os.path.join(self.locations["images"], "default_thumbnail.png"))

        # update in database
        delete.delete_poster(self, movie.poster_md5)
        movie.poster_md5 = None
        session.add(movie)
        try:
            session.commit()
        except Exception, e:
            session.rollback()
            log.error("cannot delete poster: %s" % e)
            return False

        self.update_statusbar(_("Image has been updated"))

        self.widgets["add"]["delete_poster"].set_sensitive(False)
        self.widgets["menu"]["delete_poster"].set_sensitive(False)
        self.widgets["movie"]["picture_button"].set_sensitive(False)
Пример #4
0
def delete_person(self):
    has_history = False
    has_history_msg = ""
    try:
        treeselection = self.widgets["people"]["treeview"].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        person = tmp_model.get_value(tmp_iter, 0).decode("utf-8")
    except:
        return
    person = self.db.session.query(db.Person).filter_by(name=person).first()
    if not person:
        return False
    if person.loaned_movies_count > 0:
        gutils.info(_("This person has loaned films from you. Return them first."), self.widgets["people"]["window"])
        return False
    if person.returned_movies_count > 0:
        has_history = True
        has_history_msg = _("This person has data in the loan history. This data will be erased if you continue.")

    if gutils.question(
        _("%s\nAre you sure you want to delete this person?" % has_history_msg), self.widgets["people"]["window"]
    ):
        treeselection = self.widgets["people"]["treeview"].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        self.db.session.delete(person)
        try:
            self.db.session.commit()
        except Exception, e:
            log.info(str(e))
        else:
            self.p_treemodel.remove(tmp_iter)
            self.treeview_clicked()
Пример #5
0
def delete_person(self):
    response = None
    has_history = False
    has_history_msg = ''
    try:
        treeselection = self.widgets['people']['treeview'].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        person = tmp_model.get_value(tmp_iter,0).decode('utf-8')
    except:
        return
    person = self.db.session.query(db.Person).filter_by(name=person).first()
    if not person:
        return False
    data = self.db.session.query(db.Loan).filter_by(person_id=person.person_id, return_date=None).all()
    if len(data)>0:
        gutils.info(_("This person has loaned films from you. Return them first."), self.widgets['people']['window'])
        return False
    data = self.db.session.query(db.Loan).filter_by(person_id=person.person_id).all()
    if len(data)>0:
        has_history = True
        has_history_msg = _("This person has data in the loan history. This data will be erased if you continue.")
    response = gutils.question(_("%s\nAre you sure you want to delete this person?" % has_history_msg), \
                               True, self.widgets['people']['window'])

    if response == -8:
        treeselection = self.widgets['people']['treeview'].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        self.db.session.delete(person)
        try:
            self.db.session.commit()
        except Exception, e:
            log.info(str(e))
        else:
            self.p_treemodel.remove(tmp_iter)
            self.treeview_clicked()
Пример #6
0
def delete_poster(self, movie_id=None):
    if movie_id is None:
        movie_id = self._movie_id
    session = self.db.Session()
    movie = session.query(db.Movie).filter_by(movie_id=movie_id).first()
    if not movie:
        log.error("Cannot delete unknown movie's poster!")
        return False
    if gutils.question(_("Are you sure you want to delete this poster?"), self.widgets["window"]):
        # update in database
        delete.delete_poster(self, movie.poster_md5)
        movie.poster_md5 = None
        session.add(movie)
        try:
            session.commit()
        except Exception, e:
            session.rollback()
            log.error("cannot delete poster: %s" % e)
            return False

        if self._movie_id == movie_id:
            # only if the current selected movie is the same like that one for removing poster
            image_path = gutils.get_defaultimage_fname(self)
            handler = self.widgets["movie"]["picture"].set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(image_path))
            gutils.garbage(handler)
            self.widgets["add"]["delete_poster"].set_sensitive(False)
            self.widgets["movie"]["picture_button"].set_sensitive(False)
        # always refresh the treeview entry
        update_tree_thumbnail(self, gutils.get_defaultthumbnail_fname(self))

        self.update_statusbar(_("Image has been updated"))

        return True
Пример #7
0
def delete_person(self):
    has_history = False
    has_history_msg = ''
    try:
        treeselection = self.widgets['people']['treeview'].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        person = tmp_model.get_value(tmp_iter,0).decode('utf-8')
    except:
        return
    person = self.db.session.query(db.Person).filter_by(name=person).first()
    if not person:
        return False
    if person.loaned_movies_count > 0:
        gutils.info(_("This person has loaned films from you. Return them first."), self.widgets['people']['window'])
        return False
    if person.returned_movies_count > 0:
        has_history = True
        has_history_msg = _("This person has data in the loan history. This data will be erased if you continue.")
    
    if gutils.question(_("%s\nAre you sure you want to delete this person?" % has_history_msg), self.widgets['people']['window']):
        treeselection = self.widgets['people']['treeview'].get_selection()
        (tmp_model, tmp_iter) = treeselection.get_selected()
        self.db.session.delete(person)
        try:
            self.db.session.commit()
        except Exception, e:
            log.info(str(e))
        else:
            self.p_treemodel.remove(tmp_iter)
            self.treeview_clicked()
Пример #8
0
def delete_person(self):
	response = None
	has_history = False
	has_history_msg = ''
	try:
		treeselection = self.widgets['people']['treeview'].get_selection()
		(tmp_model, tmp_iter) = treeselection.get_selected()
		person = tmp_model.get_value(tmp_iter,0)
	except:
		return
	person = self.db.Person.get_by(name=person)
	if not person:
		return False
	data = self.db.Loan.select_by(person_id=person.person_id, return_date=None)
	if len(data)>0:
		gutils.info(self, _("This person has loaned films from you. Return them first."), self.widgets['people']['window'])
		return False
	data = self.db.Loan.select_by(person_id=person.person_id)
	if len(data)>0:
		has_history = True
		has_history_msg = _("This person has data in the loan history. This data will be erased if you continue.")
	response = gutils.question(self,_("%s\nAre you sure you want to delete this person?" % has_history_msg), \
		1, self.widgets['people']['window'])

	if response == -8:
		treeselection = self.widgets['people']['treeview'].get_selection()
		(tmp_model, tmp_iter) = treeselection.get_selected()
		if person.remove_from_db():
			self.p_treemodel.remove(tmp_iter)
			self.treeview_clicked()
	self.widgets['people']['window'].present()
    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 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)
Пример #11
0
    def toolbar_icon_clicked(self, widget, movie):
        if question(_('Are you sure you want to remove %d movies?') % self.app.total):
            session = self.db.Session()

            # first: remove all dependend data (associated tags, languages, ...)
            query = select([movies_table.c.movie_id])
            # FIXME: self.app._search_conditions contains advfilter conditions only (no other filters)
            query = update_whereclause(query, self.app._search_conditions)
            query = query.where(movies_table.c.loaned==False) # don't delete loaned movies
            for movie_entry in session.execute(query):
                # tags
                query_movie_tags = delete(movie_tag_table)
                query_movie_tags = query_movie_tags.where(movie_tag_table.c.movie_id==movie_entry.movie_id)
                session.execute(query_movie_tags)
                # languages
                query_movie_lang = delete(movie_lang_table)
                query_movie_lang = query_movie_lang.where(movie_lang_table.c.movie_id==movie_entry.movie_id)
                session.execute(query_movie_lang)
                # TODO: removing posters if no longer used by another movie?

            # second: remove the movie entries
            query = delete(movies_table)
            # FIXME: self.app._search_conditions contains advfilter conditions only (no other filters)
            query = update_whereclause(query, self.app._search_conditions)
            query = query.where(movies_table.c.loaned==False) # don't delete loaned movies

            session.execute(query)
            session.commit()

            self.app.populate_treeview()
	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)
Пример #13
0
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()
Пример #14
0
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
Пример #15
0
def delete_poster(self):
    session = self.db.Session()
    movie = session.query(db.Movie).filter_by(movie_id=self._movie_id).first()
    if not movie:
        log.error("Cannot delete unknown movie's poster!")
        return False
    if gutils.question(_("Are you sure you want to delete this poster?"), self.widgets['window']):
        image_path = gutils.get_defaultimage_fname(self)
        handler = self.widgets['movie']['picture'].set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(image_path))
        gutils.garbage(handler)
        update_tree_thumbnail(self, gutils.get_defaultthumbnail_fname(self))

        # update in database
        delete.delete_poster(self, movie.poster_md5)
        movie.poster_md5 = None
        session.add(movie)
        try:
            session.commit()
        except Exception, e:
            session.rollback()
            log.error("cannot delete poster: %s" % e)
            return False

        self.update_statusbar(_("Image has been updated"))

        self.widgets['add']['delete_poster'].set_sensitive(False)
        self.widgets['movie']['picture_button'].set_sensitive(False)
Пример #16
0
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()
Пример #17
0
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
Пример #18
0
def delete_poster(self, movie_id=None):
    if movie_id is None:
        movie_id = self._movie_id
    session = self.db.Session()
    movie = session.query(db.Movie).filter_by(movie_id=movie_id).first()
    if not movie:
        log.error("Cannot delete unknown movie's poster!")
        return False
    if gutils.question(_("Are you sure you want to delete this poster?"),
                       self.widgets['window']):
        # update in database
        delete.delete_poster(self, movie.poster_md5)
        movie.poster_md5 = None
        session.add(movie)
        try:
            session.commit()
        except Exception, e:
            session.rollback()
            log.error("cannot delete poster: %s" % e)
            return False

        if self._movie_id == movie_id:
            # only if the current selected movie is the same like that one for removing poster
            image_path = gutils.get_defaultimage_fname(self)
            handler = self.widgets['movie']['picture'].set_from_pixbuf(
                gtk.gdk.pixbuf_new_from_file(image_path))
            gutils.garbage(handler)
            self.widgets['add']['delete_poster'].set_sensitive(False)
            self.widgets['movie']['picture_button'].set_sensitive(False)
        # always refresh the treeview entry
        update_tree_thumbnail(self, gutils.get_defaultthumbnail_fname(self))

        self.update_statusbar(_("Image has been updated"))

        return True
Пример #19
0
def delete_poster(self):
	movie = self.db.Movie.get_by(movie_id=self._movie_id)
	if not movie:
		self.debug.show("Can't delete unknown movie's poster!")
		return False
	response = gutils.question(self, _("Are you sure you want to delete this poster?"), 1, self.widgets['window'])
	if response==-8:
		image_path = os.path.join(self.locations['images'], 'default.png')
		handler = self.widgets['movie']['picture'].set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(image_path))
		gutils.garbage(handler)
		update_tree_thumbnail(self, os.path.join(self.locations['images'], 'default_thumbnail.png'))
		# update in database
		old_image = movie.image
		movie.image = None
		movie.update()
		movie.flush()
		self.update_statusbar(_("Image has been updated"))

		self.widgets['add']['delete_poster'].set_sensitive(False)
		self.widgets['menu']['delete_poster'].set_sensitive(False)
		self.widgets['movie']['picture_button'].set_sensitive(False)
		if old_image:
			delete.delete_poster(self, old_image)
	else:
		pass
Пример #20
0
def commit(self):
    person_name = gutils.on_combo_box_entry_changed(self.widgets['movie']['loan_to'])
    if not person_name:
        return False
    self.widgets['w_loan_to'].hide()

    person = self.db.session.query(db.Person.person_id).filter_by(name=person_name).first()
    if not person:
        log.info("loan_commit: person doesn't exist")
        return False
    if self._movie_id:
        movie = self.db.session.query(db.Movie.movie_id, db.Movie.collection_id).filter_by(movie_id=self._movie_id).first()
        if not movie:
            log.info("loan_commit: wrong movie_id")
            return False
    else:
        log.info("loan_commit: movie not selected")
        return False

    # ask if user wants to loan whole collection
    loan_whole_collection = False
    if movie.collection_id > 0:
        response = gutils.question(_("Do you want to loan whole collection?"), window=self.widgets['window'])
        if response == gtk.RESPONSE_YES:
            loan_whole_collection = True
        elif response == gtk.RESPONSE_CANCEL:
            return False
    
    resp = sql.loan_movie(self.db, movie.movie_id, person.person_id, loan_whole_collection)
    if resp == -1:
        gutils.warning(_("Collection contains loaned movie.\nLoan aborted!"))
        return False
    elif resp:
        self.update_statusbar(_("Movie loaned"))
        self.treeview_clicked()
Пример #21
0
 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
Пример #22
0
def commit_loan(self):
	person = gutils.on_combo_box_entry_changed(self.loan_to)
	if person == '' or person == None:
		return
	self.w_loan_to.hide()

	# movie is now loaned. change db
	movie_id = self.e_number.get_text()
	self.db.cursor.execute("SELECT volume_id, collection_id FROM movies WHERE number='%s'"%movie_id)
	volume_id, collection_id = self.db.cursor.fetchall()[0]
	data_person = self.db.select_person_by_name(person)

	# ask if user wants to loan whole collection
	if collection_id>0:
		loan_whole_collection = False
		response = gutils.question(self, msg=_("Do you want to loan whole collection?"), parent=self.main_window)
		if response == gtk.RESPONSE_YES:
			loan_whole_collection = True
		elif response == gtk.RESPONSE_CANCEL:
			return False

	if volume_id>0 and collection_id>0:
		if loan_whole_collection:
			self.db.update_collection(id=collection_id, volume_id=volume_id, loaned=1)
		else:
			self.db.update_volume(id=volume_id, loaned=1)
	elif collection_id>0:
		if loan_whole_collection:
			self.db.update_collection(id=collection_id, loaned=1)
		else:
			self.db.cursor.execute("UPDATE movies SET loaned='1' WHERE number='%s';" % movie_id)
	elif volume_id>0:
		self.db.update_volume(id=volume_id, loaned=1)
	else:
		self.db.cursor.execute("UPDATE movies SET loaned='1' WHERE number='%s';" % movie_id)
	self.update_statusbar(_("Movie loaned"))

	# next, we insert a new row on the loans table
	data_movie=self.db.select_movie_by_num(movie_id)
	query = "INSERT INTO 'loans'('id', 'person_id','"
	if collection_id > 0 and loan_whole_collection:
		query +="collection_id"
	elif volume_id > 0:
		query +="volume_id"
	else:
		query +="movie_id"
	query += "', 'date', 'return_date') VALUES (Null, '" + str(data_person[0]['id']) + "', '"
	if collection_id > 0 and loan_whole_collection:
		query += str(collection_id)
	elif volume_id>0:
		query += str(volume_id)
	else:
		query += str(movie_id)
	query += "', '" + str(datetime.date.today()) + "', '');"
	self.db.cursor.execute(query)
	self.db.con.commit()
	
	# finally, force a refresh
	self.treeview_clicked()
    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)
Пример #25
0
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 _show_preview(self, data):
     loader = gtk.gdk.PixbufLoader()
     loader.write(data, len(data))
     loader.close()
     handler = self.widgets['big_poster'].set_from_pixbuf(loader.get_pixbuf())
     self.widgets['poster_window'].show()
     result = gutils.question(_("Do you want to use this poster instead?"), self.widgets['window'])
     self.widgets['poster_window'].hide()
     return result
Пример #27
0
    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 _show_preview(self, data):
     loader = gtk.gdk.PixbufLoader()
     loader.write(data, len(data))
     loader.close()
     # show before set_from_pixbuf because it doesn't resize otherwise
     self.widgets["poster_window"].show()
     handler = self.widgets["big_poster"].set_from_pixbuf(loader.get_pixbuf())
     result = gutils.question(_("Do you want to use this poster instead?"), self.widgets["window"])
     self.widgets["poster_window"].hide()
     return result
Пример #29
0
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)
Пример #30
0
 def _show_preview(self, data):
     loader = gtk.gdk.PixbufLoader()
     loader.write(data, len(data))
     loader.close()
     # show before set_from_pixbuf because it doesn't resize otherwise
     self.widgets['poster_window'].show()
     handler = self.widgets['big_poster'].set_from_pixbuf(loader.get_pixbuf())
     result = gutils.question(_("Do you want to use this poster instead?"), self.widgets['window'])
     self.widgets['poster_window'].hide()
     return result
 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_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)
Пример #33
0
    def toolbar_icon_clicked(self, widget, movie):
        if question(_('Are you sure you want to update %d movies?') % self.app.total):
            session = self.db.Session()

            update_query = update(movies_table, values={'seen': True})
            # FIXME: self.app._search_conditions contains advfilter conditions only (no other filters)
            update_query = update_whereclause(update_query, self.app._search_conditions)

            session.execute(update_query)
            session.commit()

            self.app.populate_treeview() # update seen widget in the list
	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)
Пример #35
0
    def toolbar_icon_clicked(self, widget, movie):
        if question(
                _('Are you sure you want to update %d movies?') %
                self.app.total):
            session = self.db.Session()

            update_query = update(movies_table, values={'seen': True})
            # FIXME: self.app._search_conditions contains advfilter conditions only (no other filters)
            update_query = update_whereclause(update_query,
                                              self.app._search_conditions)

            session.execute(update_query)
            session.commit()

            self.app.populate_treeview()  # update seen widget in the list
Пример #36
0
def delete_poster(self):
	m_id, m_iter = self.get_maintree_selection()
	poster = self.db.select_movie_by_num(m_id)[0]['image']
	response = gutils.question(self, _("Are you sure you want to delete this poster?"), 1, self.main_window)
	if response==-8:
		image_path = self.locations['images'] + "/default.png"
		handler = self.e_picture.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(image_path))
		gutils.garbage(handler)
		update_tree_thumbnail(self, self.locations['images'] + "/default_thumbnail.png")
		m_id = self.get_maintree_selection()
		update.clear_image(self, m_id[0])
		self.delete_poster.set_sensitive(False)
		self.zoom_poster.set_sensitive(False)
		delete.delete_poster(self, poster)
	else:
		pass
Пример #37
0
def delete_movie(self):
	m_id = None
	m_id, m_iter = self.get_maintree_selection()
	if self.db.is_movie_loaned(movie_number=m_id):
		gutils.warning(self, msg=_("You can't delete movie while it is loaned."))
		return False
	response = gutils.question(self,_("Are you sure you want to delete this movie?"), \
		1, self.main_window)
	if response == -8:	# gtk.RESPONSE_YES == -8
		# try to delete poster image as well
		poster = self.db.get_value('image', table="movies", where="number='%s'"%m_id)
		if poster != None:
			delete_poster(self, poster)
		delete_movie_from_db(self, m_id, m_iter)
		self.main_treeview.set_cursor_on_cell(self.total_filter-1)
	else:
		return False
Пример #38
0
    def toolbar_icon_clicked(self, widget, movie):
        if question(
                _('Are you sure you want to remove %d movies?') %
                self.app.total):
            session = self.db.Session()

            # first: remove all dependend data (associated tags, languages, ...)
            query = select([movies_table.c.movie_id])
            # add conditions from simple filter
            change_filter_update_whereclause(self.app, query)
            # add conditions from adv filter
            query = update_whereclause(query, self.app._search_conditions)
            query = query.where(
                movies_table.c.loaned == False)  # don't delete loaned movies
            log.debug(query)
            movie_ids = []
            for movie_entry in session.execute(query):
                movie_ids.append(movie_entry.movie_id)
                # tags
                query_movie_tags = delete(movie_tag_table)
                query_movie_tags = query_movie_tags.where(
                    movie_tag_table.c.movie_id == movie_entry.movie_id)
                log.debug(query_movie_tags)
                session.execute(query_movie_tags)
                # languages
                query_movie_lang = delete(movie_lang_table)
                query_movie_lang = query_movie_lang.where(
                    movie_lang_table.c.movie_id == movie_entry.movie_id)
                log.debug(query_movie_lang)
                session.execute(query_movie_lang)
                # TODO: removing posters if no longer used by another movie?

            # second: remove the movie entries
            if len(movie_ids):
                query = delete(movies_table)
                # use the collected movie ids because other conditions are not true anymore
                # (f.e. tags are already deleted)
                query = query.where(movies_table.c.movie_id.in_(movie_ids))

                log.debug(query)
                session.execute(query)
            session.commit()

            self.app.populate_treeview()
Пример #39
0
def commit(self):
    person_name = gutils.on_combo_box_entry_changed(
        self.widgets['movie']['loan_to'])
    if not person_name:
        return False
    self.widgets['w_loan_to'].hide()

    session = self.db.Session()

    person = session.query(
        db.Person.person_id).filter_by(name=person_name).first()
    if not person:
        log.warn("loan_commit: person doesn't exist")
        return False
    if self._movie_id:
        movie = session.query(
            db.Movie).filter_by(movie_id=self._movie_id).first()
        if not movie:
            log.warn("loan_commit: movie doesn't exist")
            return False
    else:
        log.warn("loan_commit: movie not selected")
        return False

    # ask if user wants to loan whole collection
    loan_whole_collection = False
    if movie.collection_id > 0:
        if gutils.question(_('Do you want to loan the whole collection?'),
                           window=self.widgets['window']):
            loan_whole_collection = True

    try:
        if movie.loan_to(person, whole_collection=loan_whole_collection):
            session.commit()
    except Exception, e:
        session.rollback()
        if e.message == 'loaned movies in the collection already':
            gutils.warning(
                _("Collection contains loaned movie.\nLoan aborted!"))
            return False
        else:
            raise e
Пример #40
0
    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)
Пример #41
0
    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
Пример #42
0
    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)
Пример #43
0
    def get_poster(self, item):
        """Returns file path to the new poster"""

        from movie import Progress, Retriever

        file_to_copy = tempfile.mktemp(suffix=self.widgets['movie']['number'].get_text(), \
            dir=self.locations['temp'])
        file_to_copy += ".jpg"
        canceled = False
        try:
            progress = Progress(self.widgets['window'], _("Fetching poster"), _("Wait a moment"))
            retriever = Retriever(item.LargeImage.URL, self.widgets['window'], progress, file_to_copy)
            retriever.start()
            while retriever.isAlive():
                progress.pulse()
                if progress.status:
                    canceled = True
                while gtk.events_pending():
                    gtk.main_iteration()
            progress.close()
            urlcleanup()
        except:
            canceled = True
            gutils.warning(_("Sorry. A connection error has occurred."))
            try:
                os.remove(file_to_copy)
            except:
                log.error("no permission for %s" % file_to_copy)

        if not canceled:
            if os.path.isfile(file_to_copy):
                im = None
                try:
                    im = Image.open(file_to_copy)
                except IOError:
                    log.warn("failed to identify %s" % file_to_copy)

                if im and im.size == (1, 1):
                    url = FancyURLopener().open("http://www.amazon.com/gp/product/images/%s" % item.ASIN).read()
                    if url.find('no-img-sm._V47056216_.gif') > 0:
                        log.warn('No image available')
                        gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com."))
                        return False
                    url = gutils.after(url, 'id="imageViewerDiv"><img src="')
                    url = gutils.before(url, '" id="prodImage"')
                    urlretrieve(url, file_to_copy)
                    try:
                        im = Image.open(file_to_copy)
                    except IOError:
                        log.warn("failed to identify %s", file_to_copy)

                if not im:
                    # something wrong with the image, give some feedback to the user
                    log.warn('No image available')
                    gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com."))
                    return False

                if im.mode != 'RGB': # convert GIFs
                    im = im.convert('RGB')
                    im.save(file_to_copy, 'JPEG')
                # set to None because the file is locked otherwise (os.remove throws an exception)
                im = None

                handler = self.widgets['big_poster'].set_from_file(file_to_copy)

                self.widgets['poster_window'].show()
                self.widgets['poster_window'].move(0, 0)
                if gutils.question(_("Do you want to use this poster instead?"), self.widgets['window']):
                    return file_to_copy
                else:
                    log.info("Reverting to previous poster and deleting new one from disk.")
                    try:
                        os.remove(file_to_copy)
                    except:
                        log.error('cannot remove %s', file_to_copy)

                self.widgets['poster_window'].hide()
            else:
                gutils.warning(_("Sorry. This movie is listed but has no poster available at Amazon.com."))
        else:
            # cleanup temporary files after canceling the download
            if os.path.isfile(file_to_copy):
                try:
                    os.remove(file_to_copy)
                except:
                    log.error('cannot remove %s', file_to_copy)
Пример #44
0
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'])
Пример #45
0
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
Пример #46
0
    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))