Ejemplo n.º 1
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
Ejemplo n.º 2
0
def convert_from_old_db(config, source_file, destination_file, locations):  # {{{
    """
    convert .gri database into .bd one
    """

    log.info("Converting old database - it can take several minutes...")
    log.debug("Source file: %s", source_file)
    gutils.info(
        _(
            "Griffith will now convert your database to the new format. This can take several minutes if you have a large database."
        )
    )
    from sql import GriffithSQL
    from gutils import digits_only
    import os

    if not os.path.isfile(source_file):
        return False

    if "home" not in locations:
        log.error("locations doesn't contain home path, cannot convert old database")
        return False

    if open(source_file).readline()[:47] == "** This file contains an SQLite 2.1 database **":
        log.debug("SQLite 2.1 detected")
        try:
            import sqlite
        except ImportError:
            log.error("Old DB conversion: please install pysqlite legacy (v1.0)")
            gutils.warning(_("Old DB conversion: please install pysqlite legacy (v1.0)"))
            return False
    else:
        try:  # Python 2.5
            from sqlite3 import dbapi2 as sqlite
        except ImportError:  # Python < 2.5 - try to use pysqlite2
            from pysqlite2 import dbapi2 as sqlite

    if os.path.isfile(destination_file):
        # rename destination_file if it already exist
        i = 1
        while True:
            if os.path.isfile("%s_%s" % (destination_file, i)):
                i += 1
            else:
                break
        os.rename(destination_file, "%s_%s" % (destination_file, i))

    try:
        old_db = sqlite.connect(source_file)
    except sqlite.DatabaseError, e:
        if str(e) == "file is encrypted or is not a database":
            print "Your database is most probably in SQLite2 format, please convert it to SQLite3:"
            print "$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3"
            print "$ mv ~/.griffith/griffith.gri{,2}"
            print "$ mv ~/.griffith/griffith.gri{3,}"
            print "or install pysqlite in version 1.0"
            gutils.warning(_("Your database is most probably in SQLite2 format, please convert it to SQLite3"))
        else:
            raise
        return False
Ejemplo n.º 3
0
    def __init__(self, config, griffith_dir, fallback=True):
        #mapper = Session.mapper
        self.config = config
        self.data_dir = griffith_dir

        if config.get('type', None, section='database') is None:
            config.set('type', 'sqlite', section='database')

        if config.get('type', 'sqlite', section='database') != 'sqlite':
            if config.get('host', None, section='database') is None:
                config.set('host', '127.0.0.1', section='database')
            if config.get('user', None, section='database') is None:
                config.set('user', 'griffith', section='database')
            if config.get('passwd', None, section='database') is None:
                config.set('passwd', 'gRiFiTh', section='database')
            if config.get('name', None, section='database') is None:
                config.set('name', 'griffith', section='database')
            if config.get('port', 0, section='database') == 0:
                config.set('port', GriffithSQL.DEFAULT_PORTS[config.get('type', section='database')], section='database')

        conn_params = config.to_dict(section='database')
        conn_params.update({'port': int(conn_params.get('port', 0)),
                            'engine_kwargs': {'echo': False, 'convert_unicode': False}})

        # connect to database --------------------------------------{{{
        if config.get('type', section='database') == 'sqlite':
            url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name'])
        elif config.get('type', section='database') == 'postgres':
            url = "postgres://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s" % conn_params
        elif config.get('type', section='database') == 'mysql':
            conn_params['engine_kwargs']['convert_unicode'] = True
            conn_params['engine_kwargs']['pool_recycle'] = int(config.get('pool_recycle', 3600, section='database'))
            url = "mysql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?charset=utf8&use_unicode=0" % conn_params
        elif config.get('type', section='database') == 'mssql':
            # use_scope_identity=0 have to be set as workaround for a sqlalchemy bug
            # but it is not guaranteed that the right identity value will be selected
            # because the select @@identity statement selects the very last id which
            # also can be a id from a trigger-insert or another user
            # sqlalchemy uses a wrong syntax. It has to select the id within the insert
            # statement: insert <table> (<columns>) values (<values>) select scope_identity()
            # (one statement !) After preparing and executing there should be a fetch
            # If it is executed as two separate statements the scope is lost after insert.
            url = "mssql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?use_scope_identity=0" % conn_params
        else:
            config.set('type', 'sqlite', section='database')
            url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name'])

        # try to establish a db connection
        try:
            engine = create_engine(url, **conn_params['engine_kwargs'])
            conn = engine.connect()
        except Exception, e:    # InvalidRequestError, ImportError
            log.info("MetaData: %s", e)
            if not fallback:
                raise e
            config.set('type', 'sqlite', section='database')
            warning("%s\n\n%s" % (_('Cannot connect to database.\nFalling back to SQLite.'), _('Please check debug output for more informations.')))
            url = "sqlite:///%s.db" % os.path.join(griffith_dir, conn_params['name'])
            engine = create_engine(url)
            conn = engine.connect()
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def save(gsql, widgets):
    """saves search conditions from current filter window"""

    cond = get_conditions(widgets)
    name = widgets['cb_name'].get_active_text().decode('utf-8')
    if not name:
        log.debug("search rule name is empty")
        info(_("Name is empty"), widgets['window'])
        return False

    session = gsql.Session()
    filter_ = session.query(db.Filter).filter_by(name=name).first()
    if filter_:
        filter_.data = cond
        isnew = False
    else:
        filter_ = db.Filter(name=name, data=cond)
        isnew = True
    session.add(filter_)
    try:
        session.commit()
    except Exception, e:
        session.rollback()
        log.warn(e)
        warning(_("Cannot save search conditions"), widgets['window'])
        return False
Ejemplo n.º 6
0
def save(gsql, widgets):
    """saves search conditions from current filter window"""

    cond = get_conditions(widgets)
    name = widgets['cb_name'].get_active_text().decode('utf-8')
    if not name:
        log.debug("search rule name is empty")
        info(_("Name is empty"), widgets['window'])
        return False

    session = gsql.Session()
    filter_ = session.query(db.Filter).filter_by(name=name).first()
    if filter_:
        filter_.data = cond
        isnew = False
    else:
        filter_ = db.Filter(name=name, data=cond)
        isnew = True
    session.add(filter_)
    try:
        session.commit()
    except Exception, e:
        session.rollback()
        log.warn(e)
        warning(_("Cannot save search conditions"), widgets['window'])
        return False
Ejemplo n.º 7
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()
Ejemplo n.º 8
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()
Ejemplo n.º 9
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()
Ejemplo n.º 10
0
def delete(gsql, widgets):
    """deletes the current selected filter"""

    #hier muss was anderes her! nicht den text prüfen, da bei manchem anwender ein leereintrag existiert
    name = widgets['cb_name'].get_active_text().decode('utf-8')
    if not name:
        log.debug("search rule name is empty")
        info(_("Name is empty"), widgets['window'])
        return False

    session = gsql.Session()
    filter = session.query(db.Filter).filter_by(name=name).first()
    if filter:
        session.delete(filter)
        try:
            session.commit()
        except:
            session.rollback()
            log.exception('')
            warning(_("Cannot delete search conditions"), widgets['window'])
            return False
        else:
            widgets['cb_name'].remove_text(widgets['cb_name'].get_active())
        info(_("Search conditions deleted"), widgets['window'])
    widgets['name'].set_text('')
Ejemplo n.º 11
0
def commit(session):
    try:
        session.commit()
    except IntegrityError, e:
        session.rollback()
        log.warn("Cannot commit movie: %s", e.message)
        gutils.warning(unicode(e.orig))
        return False
Ejemplo n.º 12
0
def commit(self, session):
    try:
        session.commit()
    except IntegrityError, e:
        session.rollback()
        gutils.warning(self, str(e.orig))
        log.warn("Cannot commit movie: %s", e.message)
        return False
Ejemplo n.º 13
0
def fetch_bigger_poster(self):
	match = 0
	self.debug.show("fetching poster from amazon")
	movie = self.db.Movie.get_by(movie_id=self._movie_id)
	if movie is None:
		gutils.error(self,_("You have no movies in your database"), self.widgets['window'])
		return False
	current_poster = movie.image
	amazon.setLicense("04GDDMMXX8X9CJ1B22G2")

	locale = self.config.get('amazon_locale', 0, section='add')
	keyword = self.widgets['movie']['o_title'].get_text().decode('utf-8')
	if locale == '1':
		locale = 'uk'
	elif locale == '2':
		locale = 'de'
		keyword = self.widgets['movie']['title'].get_text().decode('utf-8')
	elif locale == '3':
		locale = 'ca'
	elif locale == '4':
		locale = 'fr'
	elif locale == '5':
		locale = 'jp'
	else:
		locale = None

	try:
		result = amazon.searchByKeyword(keyword, type="Large", product_line="DVD", locale=locale)
		self.debug.show("Posters found on amazon: %s posters" % result.TotalResults)
	except:
		gutils.warning(self, _("No posters found for this movie."))
		return

	from widgets import connect_poster_signals, reconnect_add_signals
	connect_poster_signals(self, get_poster_select_dc, result, current_poster)

	if not len(result.Item):
		gutils.warning(self, _("No posters found for this movie."))
		reconnect_add_signals(self)
		return

	for f in range(len(result.Item)):
		if self.widgets['movie']['o_title'].get_text().decode('utf-8') == result.Item[f].ItemAttributes.Title:
			get_poster(self, f, result, current_poster)
			return

	self.treemodel_results.clear()
	self.widgets['add']['b_get_from_web'].set_sensitive(False) # disable movie plugins (result window is shared)

	for f in range(len(result.Item)):
		if hasattr(result.Item[f], "LargeImage") and len(result.Item[f].LargeImage.URL):
			title = result.Item[f].ItemAttributes.Title
			myiter = self.treemodel_results.insert_before(None, None)
			self.treemodel_results.set_value(myiter, 0, str(f))
			self.treemodel_results.set_value(myiter, 1, title)

	self.widgets['results']['window'].show()
	self.widgets['results']['window'].set_keep_above(True)
Ejemplo n.º 14
0
def fetch_bigger_poster(self):
    match = 0
    self.debug.show("fetching poster from amazon")
    movie = self.db.Movie.get_by(movie_id=self._movie_id)
    if movie is None:
        gutils.error(self, _("You have no movies in your database"), self.widgets["window"])
        return False
    current_poster = movie.image
    amazon.setLicense("04GDDMMXX8X9CJ1B22G2")

    locale = self.config.get("amazon_locale", 0)
    if locale == 1:
        locale = "uk"
    elif locale == 2:
        locale = "de"
    elif locale == 3:
        locale = "uk"
    else:
        locale = None

    try:
        result = amazon.searchByKeyword(
            self.widgets["movie"]["o_title"].get_text(), type="lite", product_line="dvd", locale=locale
        )
        self.debug.show("Posters found on amazon: %s posters" % len(result))
    except:
        gutils.warning(self, _("No posters found for this movie."))
        return

    from widgets import connect_poster_signals, reconnect_add_signals

    connect_poster_signals(self, get_poster_select_dc, result, current_poster)

    if not len(result):
        gutils.warning(self, _("No posters found for this movie."))
        reconnect_add_signals(self)
        return

    for f in range(len(result)):
        if self.widgets["movie"]["o_title"].get_text() == result[f].ProductName:
            get_poster(self, f, result, current_poster)
            return

    self.treemodel_results.clear()
    self.widgets["add"]["b_get_from_web"].set_sensitive(False)  # disable movie plugins (result window is shared)

    for f in range(len(result)):

        if len(result[f].ImageUrlLarge):
            title = result[f].ProductName
            myiter = self.treemodel_results.insert_before(None, None)
            self.treemodel_results.set_value(myiter, 0, str(f))
            self.treemodel_results.set_value(myiter, 1, title)

    self.widgets["results"]["window"].show()
    self.widgets["results"]["window"].set_keep_above(True)
Ejemplo n.º 15
0
def update_person(self):
    p = self.db.session.query(db.Person).filter_by(person_id=self.widgets['person']['e_id'].get_text().decode('utf-8')).first()
    if not p:
        log.warning('Person not found')
        return False
    try:
        p.name = self.widgets['person']['e_name'].get_text().decode('utf-8')
        p.email = self.widgets['person']['e_email'].get_text().decode('utf-8')
        p.phone = self.widgets['person']['e_phone'].get_text().decode('utf-8')
    except ValueError, e:
        gutils.warning(e.message)
        return False
    def export_data(self, widget):
        """Main exporting function"""

        config = self.settings
        fields = self.fields
        tid = config["template"]

        # get data from widgets
        self.settings["export_dir"] = self.widgets["fcw"].get_filename()
        self.settings["title"] = self.widgets["entry_header"].get_text().decode("utf-8")
        self.settings["sorting"] = self.names[self.widgets["combo_sortby"].get_active_text().decode("utf-8")]
        if self.widgets["cb_reverse"].get_active():
            self.settings["sorting2"] = "DESC"
        else:
            self.settings["sorting2"] = "ASC"
        self.settings["split_num"] = self.widgets["sb_split_num"].get_value_as_int()
        self.settings["poster_height"] = self.widgets["sb_height"].get_value_as_int()
        self.settings["poster_width"] = self.widgets["sb_width"].get_value_as_int()
        if self.widgets["cb_black"].get_active():
            self.settings["poster_mode"] = "L"
        else:
            self.settings["poster_mode"] = "RGB"
        self.settings["poster_format"] = self.widgets["combo_format"].get_active_text()

        # persist config
        if self.config is not None:
            for name, value in config.items():
                self.config.set(name, value, section="export-html")
            selected_fields = ""
            for name, value in self.fields.items():
                if value:
                    selected_fields = selected_fields + name + ","
            self.config.set("selected_fields", selected_fields, section="export-html")
            self.config.save()

        # create directories
        if not config["export_dir"]:
            log.info("Error: Folder name not set!")
            return 1

        if not os.path.isdir(config["export_dir"]):
            try:
                os.mkdir(config["export_dir"])
            except:
                gutils.error(_("Can't create %s!") % config["export_dir"])
                return 2

        data_path = os.path.join(self.locations["share"], "export_templates", self.templates[tid]["dir"], "data")
        if os.path.isdir(data_path):
            try:
                gutils.copytree(data_path, config["export_dir"])
            except Exception, err:
                gutils.warning(str(err))
Ejemplo n.º 17
0
def update_person(self):
    p = self.db.session.query(db.Person).filter_by(person_id=self.widgets['person']['e_id'].get_text().decode('utf-8')).first()
    if not p:
        log.warning('Person not found')
        return False
    try:
        p.name = self.widgets['person']['e_name'].get_text().decode('utf-8')
        p.email = self.widgets['person']['e_email'].get_text().decode('utf-8')
        p.phone = self.widgets['person']['e_phone'].get_text().decode('utf-8')
    except ValueError, e:
        gutils.warning(e.message)
        return False
    def export_data(self, widget):
        """Main exporting function"""

        config = self.settings
        fields = self.fields
        tid = config['template']
        
        # get data from widgets
        self.settings['export_dir']   = self.widgets['fcw'].get_filename()
        self.settings['title']        = self.widgets['entry_header'].get_text().decode('utf-8')
        self.settings['sorting']      = self.names[self.widgets['combo_sortby'].get_active_text().decode('utf-8')]
        if self.widgets['cb_reverse'].get_active():
            self.settings['sorting2'] = 'DESC'
        else:
            self.settings['sorting2'] = 'ASC'
        self.settings['split_num']     = self.widgets['sb_split_num'].get_value_as_int()
        self.settings['poster_height'] = self.widgets['sb_height'].get_value_as_int()
        self.settings['poster_width']  = self.widgets['sb_width'].get_value_as_int()
        if self.widgets['cb_black'].get_active():
            self.settings['poster_mode'] = 'L'
        else:
            self.settings['poster_mode'] = 'RGB'
        self.settings['poster_format'] = self.widgets['combo_format'].get_active_text()

        # persist config
        if self.config is not None:
            for name, value in config.items():
                self.config.set(name, value, section='export-html')
            selected_fields = ''
            for name, value in self.fields.items():
                if value:
                    selected_fields = selected_fields + name + ','
            self.config.set('selected_fields', selected_fields, section='export-html')
            self.config.save()

        # create directories
        if not config['export_dir']:
            log.info("Error: Folder name not set!")
            return 1
        
        if not os.path.isdir(config['export_dir']):
            try:
                os.mkdir(config['export_dir'])
            except:
                gutils.error(_("Can't create %s!") % config['export_dir'])
                return 2
            
        data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data')
        if os.path.isdir(data_path):
            try:
                gutils.copytree(data_path, config['export_dir'])
            except Exception, err:
                gutils.warning(str(err))
Ejemplo n.º 19
0
def convert_from_old_db(self, source_file, destination_file):	#{{{
	print 'Converting old database - it can take several minutes...'
	gutils.info(self,_("Griffith will now convert your database to the new format. This can take several minutes if you have a large database."))
	from sqlalchemy.orm import clear_mappers
	from sql import GriffithSQL
	from gutils import digits_only
	import os

	if not os.path.isfile(source_file):
		return False
	if open(source_file).readline()[:47] == '** This file contains an SQLite 2.1 database **':
		try:
			import sqlite
			from sqlite import DatabaseError
		except ImportError:
			print 'Old DB conversion: please install pysqlite legacy (v1.0)'
			gutils.warning(self,_("Old DB conversion: please install pysqlite legacy (v1.0)"))
			return False
	else:
		try:	# Python 2.5
			from sqlite3 import dbapi2 as sqlite
			from sqlite3.dbapi2 import DatabaseError
		except ImportError: # Python < 2.5 - try to use pysqlite2
			from pysqlite2 import dbapi2 as sqlite
			from pysqlite2.dbapi2 import DatabaseError

	if os.path.isfile(destination_file):
		# rename destination_file if it already exist
		i = 1
		while True:
			if os.path.isfile("%s_%s" % (destination_file, i)):
				i += 1
			else:
				break
		os.rename(destination_file, "%s_%s" % (destination_file, i))

	try:
		old_db = sqlite.connect(source_file)
	except DatabaseError, e:
		if str(e) == 'file is encrypted or is not a database':
			print 'Your database is most probably in wrong SQLite format, please convert it to SQLite3:'
			print '$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3'
			print '$ mv ~/.griffith/griffith.gri{,2}'
			print '$ mv ~/.griffith/griffith.gri{3,}'
			print 'or install pysqlite in version 1.0'
			gutils.warning(self,_("Your database is most probably in SQLite2 format, please convert it to SQLite3"))
		else:
			raise
		return False
Ejemplo n.º 20
0
	def update_collection(self, id, name=None, volume_id=None, loaned=None):
		if str(id) == '0':
			self.debug.show("You have to select collection first")
			return False
		if name!=None:
			tmp = self.get_value(field="id", table="collections", where="name='%s'"%name)
			if tmp != None:
				self.debug.show("This name is already in use (id=%s)"%tmp)
				gutils.warning(self, msg="This name is already in use!")
				return False
			try:
				self.cursor.execute("UPDATE collections SET name = '%s' WHERE id = '%s';"%(name,id))
			except:
				self.debug.show("ERROR during updating collection's name!")
				return False
			return True
		if loaned==1:
			try:
				self.cursor.execute("""
					UPDATE collections SET loaned='1' WHERE id='%s';
					UPDATE movies SET loaned='1' WHERE collection_id='%s';
				""" % (id, id))
			except:
				self.debug.show("ERROR during updating collection's loan data!")
				return False
			if volume_id:
				try:
					self.cursor.execute("UPDATE volumes SET loaned='1' WHERE id='%s';"%volume_id)
				except:
					self.debug.show("ERROR during updating volume's loan data!")
					return False
			return True
		elif loaned==0:
			try:
				self.cursor.execute("""
					UPDATE collections SET loaned='0' WHERE id='%s';
					UPDATE movies SET loaned='0' WHERE collection_id='%s';
				""" %( id, id))
			except:
				self.debug.show("ERROR during updating collection's loan data!")
				return False
			if volume_id:
				try:
					self.cursor.execute("UPDATE volumes SET loaned='0' WHERE id='%s';"%volume_id)
				except:
					self.debug.show("ERROR during updating volume's loan data!")
					return False
			return True
		return False
Ejemplo n.º 21
0
	def update_language(self, id, name):
		if str(id) == '0':
			self.debug.show("You have to select language first")
			return False
		tmp = self.get_value(field="id", table="languages", where="name='%s'"%name)
		if tmp != None:
			self.debug.show("This name is already in use (id=%s)"%tmp)
			gutils.warning(self, msg="This name is already in use!")
			return False
		try:
			self.cursor.execute("UPDATE languages SET name ='%s' WHERE id='%s';" % (name, id))
		except:
			self.debug.show("ERROR during updating language name!")
			return False
		return True
Ejemplo n.º 22
0
def update_person(self):
    p = (
        self.db.session.query(db.Person)
        .filter_by(person_id=self.widgets["person"]["e_id"].get_text().decode("utf-8"))
        .first()
    )
    if not p:
        log.warning("Person not found")
        return False
    try:
        p.name = self.widgets["person"]["e_name"].get_text().decode("utf-8")
        p.email = self.widgets["person"]["e_email"].get_text().decode("utf-8")
        p.phone = self.widgets["person"]["e_phone"].get_text().decode("utf-8")
    except ValueError, e:
        gutils.warning(e.message)
        return False
Ejemplo n.º 23
0
def add_person_db(self):
    name = self.widgets['person']['name'].get_text().decode('utf-8')
    if name:
        p = db.Person()
        try:
            p.name = self.widgets['person']['name'].get_text().decode('utf-8')
            p.email = self.widgets['person']['email'].get_text().decode('utf-8')
            p.phone = gutils.digits_only(self.widgets['person']['phone'].get_text().decode('utf-8'))
        except ValueError, e:
            gutils.warning(e.message)
            return False
        self.widgets['person']['window'].hide()
        self.db.session.add(p)
        try:
            self.db.session.commit()
        except Exception, e:
            log.info(str(e))
Ejemplo n.º 24
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
Ejemplo n.º 25
0
def add_person_db(self):
    name = self.widgets['person']['name'].get_text().decode('utf-8')
    if name:
        p = db.Person()
        try:
            p.name = self.widgets['person']['name'].get_text().decode('utf-8')
            p.email = self.widgets['person']['email'].get_text().decode('utf-8')
            p.phone = gutils.digits_only(self.widgets['person']['phone'].get_text().decode('utf-8'))
        except ValueError, e:
            gutils.warning(e.message)
            return False
        self.widgets['person']['window'].hide()
        self.db.session.add(p)
        try:
            self.db.session.commit()
        except Exception, e:
            self.db.session.rollback()
            log.info(str(e))
Ejemplo n.º 26
0
	def update_tag(self, id, name):
		if id == None:
			self.debug.show("You have to select tag first")
			return False
		if name == '':
			self.debug.show("Tag's name is empty")
			return False
		tmp = self.get_value(field="id", table="tags", where="name='%s'"%name)
		if tmp != None:
			self.debug.show("This name is already in use (id=%s)"%tmp)
			gutils.warning(self, msg="This name is already in use!")
			return False
		try:
			self.cursor.execute("UPDATE tags SET name ='%s' WHERE id='%s';" % (name,id))
		except:
			self.debug.show("ERROR during updating tag name!")
			return False
		return True
Ejemplo n.º 27
0
def add_person_db(self):
    name = self.widgets["person"]["name"].get_text().decode("utf-8")
    if name:
        p = db.Person()
        try:
            p.name = self.widgets["person"]["name"].get_text().decode("utf-8")
            p.email = self.widgets["person"]["email"].get_text().decode("utf-8")
            p.phone = gutils.digits_only(self.widgets["person"]["phone"].get_text().decode("utf-8"))
        except ValueError, e:
            gutils.warning(e.message)
            return False
        self.widgets["person"]["window"].hide()
        self.db.session.add(p)
        try:
            self.db.session.commit()
        except Exception, e:
            self.db.session.rollback()
            log.info(str(e))
    def export_data(self, widget):
        """Main exporting function"""

        config = self.config
        fields = self.fields
        tid = config["template"]

        # get data from widgets
        self.config["exported_dir"] = self.widgets["fcw"].get_filename()
        self.config["title"] = self.widgets["entry_header"].get_text()
        self.config["sorting"] = self.names[self.widgets["combo_sortby"].get_active_text()]
        if self.widgets["cb_reverse"].get_active():
            self.config["sorting2"] = "DESC"
        else:
            self.config["sorting2"] = "ASC"
        self.config["split_num"] = self.widgets["sb_split_num"].get_value_as_int()
        self.config["poster_height"] = self.widgets["sb_height"].get_value_as_int()
        self.config["poster_width"] = self.widgets["sb_width"].get_value_as_int()
        if self.widgets["cb_black"].get_active():
            self.config["poster_mode"] = "L"
        else:
            self.config["poster_mode"] = "RGB"
        self.config["poster_format"] = self.widgets["combo_format"].get_active_text()

        # create directories
        if not config["exported_dir"]:
            self.debug.show("Error: Folder name not set!")
            return 1

        if not os.path.isdir(config["exported_dir"]):
            try:
                os.mkdir(config["exported_dir"])
            except:
                gutils.error(self, _("Can't create %s!") % config["exported_dir"])
                return 2

        data_path = os.path.join(self.locations["share"], "export_templates", self.templates[tid]["dir"], "data")
        if os.path.isdir(data_path):
            try:
                gutils.copytree(data_path, config["exported_dir"])
            except Exception, err:
                gutils.warning(self, str(err))
Ejemplo n.º 29
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
	def export_data(self, widget):
		"""Main exporting function"""

		config = self.config
		fields = self.fields
		tid = config['template']
		
		# get data from widgets
		self.config['exported_dir'] = self.widgets['fcw'].get_filename()
		self.config['title']        = self.widgets['entry_header'].get_text()
		self.config['sorting']      = self.names[self.widgets['combo_sortby'].get_active_text()]
		if self.widgets['cb_reverse'].get_active():
			self.config['sorting2'] = 'DESC'
		else:
			self.config['sorting2'] = 'ASC'
		self.config['split_num']     = self.widgets['sb_split_num'].get_value_as_int()
		self.config['poster_height'] = self.widgets['sb_height'].get_value_as_int()
		self.config['poster_width']  = self.widgets['sb_width'].get_value_as_int()
		if self.widgets['cb_black'].get_active():
			self.config['poster_mode'] = 'L'
		else:
			self.config['poster_mode'] = 'RGB'
		self.config['poster_format'] = self.widgets['combo_format'].get_active_text()

		# create directories
		if not config['exported_dir']:
			self.debug.show("Error: Folder name not set!")
			return 1
		
		if not os.path.isdir(config['exported_dir']):
			try:
				os.mkdir(config['exported_dir'])
			except:
				gutils.error(self,_("Can't create %s!") % config['exported_dir'])
				return 2
			
		data_path = os.path.join(self.locations['share'], 'export_templates', self.templates[tid]['dir'], 'data')
		if os.path.isdir(data_path):
			try:
				gutils.copytree(data_path, config['exported_dir'])
			except Exception, err:
				gutils.warning(self, str(err))
Ejemplo n.º 31
0
	def remove_collection(self, id=None, name=None):
		if id != None:
			name = self.get_value(field="name", table="collections", where="id = '%s'" % id)
		elif name != None and name != '' and id == None:
			name =	gutils.gescape(name)
			id = self.get_value(field="id", table="collections", where="name = '%s'" % name)
			id = str(int(id))
		if str(id) == '0' or id == None:
			self.debug.show("You have to select collection first")
			return False
		movies = int(self.get_value(field="count(id)", table="movies", where="collection_id = '%s'" % id))
		if movies > 0:
			gutils.warning(self, msg="%s movie(s) in this collection.\nRemoval is possible only if there is no movie assigned to collection"%str(movies))
			return False
		self.debug.show("Removing '%s' collection (id=%s) from database..."%(name, id))
		try:
			self.cursor.execute("DELETE FROM collections WHERE id = '%s'" % id)
		except:
				return False
		return True
Ejemplo n.º 32
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:
        response = gutils.question(_("Do you want to loan whole collection?"), window=self.widgets['window'])
        if response == gtk.RESPONSE_YES:
            loan_whole_collection = True
        elif response == gtk.RESPONSE_CANCEL:
            return False
    
    try:
        if movie.loan_to(person, whole_collection=loan_whole_collection):
            session.commit()
    except Exception, e:
        session.rollback()
        if e.message == 'loaned movies in the collection already':
            gutils.warning(_("Collection contains loaned movie.\nLoan aborted!"))
            return False
        else:
            raise e
Ejemplo n.º 33
0
	def remove_tag(self, id=None, name=None):
		if id != None:
			name = self.get_value(field="name", table="tags", where="id = '%s'"%id)
		elif name != None and name != '' and id == None:
			name =	gutils.gescape(name)
			id = self.get_value(field="id", table="tags", where="name = '%s'"%name)
			id = str(int(id))
		if str(id) == '0' or id == None:
			self.debug.show("You have to select tag first")
			return False

		movies = int(self.get_value(field="count(movie_id)", table="movie_tag", where="tag_id = '%s'" % id))
		if movies > 0:
			gutils.warning(self, msg="%s movie(s) are assigned to this tag.\nChange movie details first!"%str(movies))
			return False

		self.debug.show("Removing '%s' tag (id=%s) from database..."%(name, id))
		try:
			self.cursor.execute("DELETE FROM tags WHERE id = '%s'" % id)
		except:
				return False
		return True
Ejemplo n.º 34
0
def fetch_bigger_poster(self):
	match = 0
	self.debug.show("fetching poster from amazon")
	this_movie = self.db.select_movie_by_num(self.e_number.get_text())
	current_poster = this_movie[0]['image']
	amazon.setLicense("04GDDMMXX8X9CJ1B22G2")

	try:
		result = amazon.searchByKeyword(self.e_original_title.get_text(), \
						type="lite", product_line="dvd")
		self.debug.show("Posters found on amazon: %s posters" % len(result))
	except:
		gutils.warning(self, _("No posters found for this movie."))
		return

	widgets.connect_poster_signals(self, get_poster_select_dc, result, current_poster)

	if not len(result):
		gutils.warning(self, _("No posters found for this movie."))
		return

	for f in range(len(result)):
		if self.e_original_title.get_text() == result[f].ProductName:
			get_poster(self, f, result, current_poster)
			return

	self.treemodel_results.clear()

	for f in range(len(result)):

		if (len(result[f].ImageUrlLarge)):
			title = result[f].ProductName
			self.debug.show(title)
			myiter = self.treemodel_results.insert_before(None, None)
			self.treemodel_results.set_value(myiter, 0, str(f))
			self.treemodel_results.set_value(myiter, 1, title)

	self.w_results.show()
	self.w_results.set_keep_above(True)
Ejemplo n.º 35
0
def convert_from_old_db(self, source_file, destination_file):	#{{{
	# TODO: table.insert().execute({'number':1, 'o_title':'test1'}, {'number':2, 'title: 'test2'}) is faster!
	print 'Converting old database - it can take several minutes...'
	gutils.info(self,_("Griffith will now convert your database to the new format. This can take several minutes if you have a large database."))
	from sqlalchemy.orm import clear_mappers
	from sql import GriffithSQL
	from gutils import digits_only
	import os
	try:
		import sqlite
		from sqlite import DatabaseError
	except:
		print 'Old DB conversion: please install pysqlite legacy (v1.0)'
		gutils.warning(self,_("Old DB conversion: please install pysqlite legacy (v1.0)"))
		return False

	if os.path.isfile(destination_file):
		# rename destination_file if it already exist
		i = 1
		while True:
			if os.path.isfile("%s_%s" % (destination_file, i)):
				i += 1
			else:
				break
		os.rename(destination_file, "%s_%s" % (destination_file, i))

	try:
		old_db = sqlite.connect(source_file,autocommit=0)
	except DatabaseError, e:
		if str(e) == 'file is encrypted or is not a database':
			print 'Your database is most probably in SQLite3 format, please convert it to SQLite2:'
			print '$ sqlite3 ~/.griffith/griffith.gri .dump | sqlite ~/.griffith/griffith.gri2'
			print '$ mv ~/.griffith/griffith.gri{,3}'
			print '$ mv ~/.griffith/griffith.gri{2,}'
			print 'or install pysqlite in version 1.1'
			gutils.warning(self,_("Your database is most probably in SQLite3 format, please convert it to SQLite2"))
		else:
			raise
		return False
Ejemplo n.º 36
0
def delete(gsql, widgets):
    """deletes the current selected filter"""

    name = widgets['cb_name'].get_active_text().decode('utf-8')
    if not name:
        log.debug("search rule name is empty")
        info(_("Name is empty"), widgets['window'])
        return False

    session = gsql.Session()
    filter = session.query(db.Filter).filter_by(name=name).first()
    if filter:
        session.delete(filter)
        try:
            session.commit()
        except:
            session.rollback()
            log.exception('')
            warning(_("Cannot delete search conditions"), widgets['window'])
            return False
        else:
            widgets['cb_name'].remove_text(widgets['cb_name'].get_active())
        info(_("Search conditions deleted"), widgets['window'])
    widgets['name'].set_text('')
Ejemplo n.º 37
0
def convert_from_old_db(config, source_file, destination_file,
                        locations):  #{{{
    """
    convert .gri database into .bd one
    """

    log.info('Converting old database - it can take several minutes...')
    log.debug("Source file: %s", source_file)
    gutils.info(
        _("Griffith will now convert your database to the new format. This can take several minutes if you have a large database."
          ))
    from sql import GriffithSQL
    from gutils import digits_only
    import os

    if not os.path.isfile(source_file):
        return False

    if 'home' not in locations:
        log.error(
            "locations doesn't contain home path, cannot convert old database")
        return False

    if open(source_file).readline(
    )[:47] == '** This file contains an SQLite 2.1 database **':
        log.debug('SQLite 2.1 detected')
        try:
            import sqlite
        except ImportError:
            log.error(
                'Old DB conversion: please install pysqlite legacy (v1.0)')
            gutils.warning(
                _("Old DB conversion: please install pysqlite legacy (v1.0)"))
            return False
    else:
        try:  # Python 2.5
            from sqlite3 import dbapi2 as sqlite
        except ImportError:  # Python < 2.5 - try to use pysqlite2
            from pysqlite2 import dbapi2 as sqlite

    if os.path.isfile(destination_file):
        # rename destination_file if it already exist
        i = 1
        while True:
            if os.path.isfile("%s_%s" % (destination_file, i)):
                i += 1
            else:
                break
        os.rename(destination_file, "%s_%s" % (destination_file, i))

    try:
        old_db = sqlite.connect(source_file)
    except sqlite.DatabaseError, e:
        if str(e) == 'file is encrypted or is not a database':
            print 'Your database is most probably in SQLite2 format, please convert it to SQLite3:'
            print '$ sqlite ~/.griffith/griffith.gri .dump | sqlite3 ~/.griffith/griffith.gri3'
            print '$ mv ~/.griffith/griffith.gri{,2}'
            print '$ mv ~/.griffith/griffith.gri{3,}'
            print 'or install pysqlite in version 1.0'
            gutils.warning(
                _("Your database is most probably in SQLite2 format, please convert it to SQLite3"
                  ))
        else:
            raise
        return False
Ejemplo n.º 38
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
Ejemplo n.º 39
0
    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))
Ejemplo n.º 40
0
def get_poster(self, f, result, current_poster):
	if f == None:
		treeselection = self.results_treeview.get_selection()
		(tmp_model, tmp_iter) = treeselection.get_selected()
		f = int(tmp_model.get_value(tmp_iter, 0))
		self.w_results.hide()

	file_to_copy = tempfile.mktemp(suffix=self.e_number.get_text(), prefix='poster_', \
		dir=os.path.join(self.griffith_dir, "posters"))
	file_to_copy += ".jpg"
	try:
		progress = movie.Progress(self.main_window,_("Fetching poster"),_("Wait a moment"))
		retriever = movie.Retriever(result[f].ImageUrlLarge, self.main_window, progress, file_to_copy)
		retriever.start()
		while retriever.isAlive():
			progress.pulse()
			if progress.status:
				retriever.suspend()
			while gtk.events_pending():
				gtk.main_iteration()
		progress.close()
		urlcleanup()
	except:
		gutils.warning(self, _("Sorry. A connection error was occurred."))

	self.debug.show(file_to_copy)

	if  os.path.isfile(file_to_copy):
		handler = self.big_poster.set_from_file(file_to_copy)
		gutils.garbage(handler)

		try:
		    im = Image.open(file_to_copy)
		except IOError:
		    self.debug.show("failed to identify %s"%file_to_copy)
		else:
		    if im.format == "GIF":
				gutils.warning(self, _("Sorry. This poster image format is not supported."))
				os.remove(file_to_copy)
				return
		self.poster_window.show()
		self.poster_window.move(0,0)
		response = \
				gutils.question(self, \
				_("Do you want to use this poster instead?"), \
				1, self.main_window)
		if response == -8:
			self.debug.show("Using new fetched poster, updating and removing old one from disk.")
			update.update_image(self, os.path.basename(file_to_copy), self.e_number.get_text())
			gutils.make_thumbnail(self, '%s' % os.path.basename(file_to_copy))
			gutils.make_medium_image(self, '%s' % os.path.basename(file_to_copy))
			update_tree_thumbnail(self, '%s/posters/t_%s' % (self.griffith_dir, \
				os.path.basename(file_to_copy)))
			self.e_picture.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file(os.path.join(self.griffith_dir, "posters/m_%s"%os.path.basename(file_to_copy))))
			delete.delete_poster(self, current_poster)

		else:
			self.debug.show("Reverting to previous poster and deleting new one from disk.")
			try:
                            os.remove(file_to_copy)
                        except:
                            self.debug.show("no permission for %s"%file_to_copy)

		self.poster_window.hide()
	else:
		gutils.warning(self, _("Sorry. This movie is listed but have no poster available at Amazon.com."))
Ejemplo n.º 41
0
    def __init__(self, config, griffith_dir, fallback=True):
        #mapper = Session.mapper
        self.config = config
        self.data_dir = griffith_dir

        if config.get('type', None, section='database') is None:
            config.set('type', 'sqlite', section='database')

        if config.get('type', 'sqlite', section='database') != 'sqlite':
            if config.get('host', None, section='database') is None:
                config.set('host', '127.0.0.1', section='database')
            if config.get('user', None, section='database') is None:
                config.set('user', 'griffith', section='database')
            if config.get('passwd', None, section='database') is None:
                config.set('passwd', 'gRiFiTh', section='database')
            if config.get('name', None, section='database') is None:
                config.set('name', 'griffith', section='database')
            if config.get('port', 0, section='database') == 0:
                config.set('port',
                           GriffithSQL.DEFAULT_PORTS[config.get(
                               'type', section='database')],
                           section='database')

        conn_params = config.to_dict(section='database')
        conn_params.update({
            'port': int(conn_params.get('port', 0)),
            'engine_kwargs': {
                'echo': False,
                'convert_unicode': False
            }
        })

        # connect to database --------------------------------------{{{
        dbinitializingsql = None
        if config.get('type', section='database') == 'sqlite':
            sqlitefile = "%s.db" % os.path.join(griffith_dir,
                                                conn_params['name'])
            if not os.path.isfile(sqlitefile):
                # for new created database this is an optimization step syncing the database page size
                # to the filesystem page size
                dbinitializingsql = 'PRAGMA page_size=' + str(
                    get_filesystem_pagesize(sqlitefile))
            url = "sqlite:///%s" % sqlitefile
        elif config.get('type', section='database') == 'postgres':
            # sqlalchemy version check because postgres dialect is renamed in sqlalchemy>=0.6 from postgres to postgresql
            from sqlalchemy import __version__ as sqlalchemyversion
            if map(int, sqlalchemyversion[:3].split('.')) < [0, 6]:
                url = "postgres"
            else:
                url = "postgresql"
            url = url + "://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s" % conn_params
        elif config.get('type', section='database') == 'mysql':
            conn_params['engine_kwargs']['convert_unicode'] = True
            conn_params['engine_kwargs']['pool_recycle'] = int(
                config.get('pool_recycle', 3600, section='database'))
            url = "mysql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?charset=utf8&use_unicode=0" % conn_params
        elif config.get('type', section='database') == 'mssql':
            # use_scope_identity=0 have to be set as workaround for a sqlalchemy bug
            # but it is not guaranteed that the right identity value will be selected
            # because the select @@identity statement selects the very last id which
            # also can be a id from a trigger-insert or another user
            # sqlalchemy uses a wrong syntax. It has to select the id within the insert
            # statement: insert <table> (<columns>) values (<values>) select scope_identity()
            # (one statement !) After preparing and executing there should be a fetch
            # If it is executed as two separate statements the scope is lost after insert.
            url = "mssql://%(user)s:%(passwd)s@%(host)s:%(port)d/%(name)s?use_scope_identity=0" % conn_params
        else:
            config.set('type', 'sqlite', section='database')
            url = "sqlite:///%s.db" % os.path.join(griffith_dir,
                                                   conn_params['name'])

        # try to establish a db connection
        try:
            engine = create_engine(url, **conn_params['engine_kwargs'])
            conn = engine.connect()
            if dbinitializingsql is not None:
                engine.execute(dbinitializingsql)
        except Exception, e:  # InvalidRequestError, ImportError
            log.info("MetaData: %s", e)
            if not fallback:
                raise e
            config.set('type', 'sqlite', section='database')
            warning("%s\n\n%s" %
                    (_('Cannot connect to database.\nFalling back to SQLite.'),
                     _('Please check debug output for more informations.')))
            url = "sqlite:///%s.db" % os.path.join(griffith_dir,
                                                   conn_params['name'])
            engine = create_engine(url)
            conn = engine.connect()
Ejemplo n.º 42
0
            log.info(e)
            v = 0
        except Exception, e:
            log.error(e)
            v = 0

        if v is not None and v > 1:
            v = int(v.value)
        if v < self.version:
            from dbupgrade import upgrade_database
            if not upgrade_database(self, v, config):
                raise Exception('cannot upgrade database')
        elif v > self.version:
            log.error("database version mismatch (detected:%s; current:%s)", v,
                      self.version)
            warning(_('This database requires newer version of Griffith.'))
            raise Exception("database version mismatch")

    def dispose(self):
        # close every session and connection so that a sqlite database file can be removed
        # otherwise it will remain opened by the current process and can't be deleted
        try:
            self.session.close()
            self.Session.close_all()
            self.engine.dispose()
            del self.session
            del self.Session
            del self.engine
        except:
            log.exception('')
Ejemplo n.º 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)
Ejemplo n.º 44
0
    def toolbar_icon_clicked(self, widget, movie):
        log.info('fetching poster from Amazon...')
        self.movie = movie

        locale = self.get_config_value('locale', 'US').lower()
        accesskey = self.get_config_value('accesskey')
        secretkey = self.get_config_value('secretkey')

        if not accesskey or not secretkey:
            gutils.error(_('Please configure your Amazon Access Key ID and Secret Key correctly in the preferences dialog.'))
            return False

        if movie is None:
            gutils.error(_('You have no movies in your database'), self.widgets['window'])
            return False

        keyword = movie.o_title
        if locale == 'de':
            keyword = movie.title

        try:
            amazon.setLicense(accesskey, secretkey)
            result = amazon.searchByTitle(keyword, type='Large', product_line='DVD', locale=locale)
            if hasattr(result, 'TotalPages'):
                # get next result pages
                pages = int(result.TotalPages)
                page = 2
                while page <= pages and page < 11:
                    tmp = amazon.searchByTitle(keyword, type='Large', product_line='DVD', locale=locale, page=page)
                    result.Item.extend(tmp.Item)
                    page = page + 1
            if not hasattr(result, 'Item') or not len(result.Item):
                # fallback if nothing is found by title
                result = amazon.searchByKeyword(keyword, type='Large', product_line='DVD', locale=locale)
                if hasattr(result, 'TotalPages'):
                    # get next result pages
                    pages = int(result.TotalPages)
                    page = 2
                    while page <= pages and page < 11:
                        tmp = amazon.searchByKeyword(keyword, type='Large', product_line='DVD', locale=locale, page=page)
                        result.Item.extend(tmp.Item)
                        page = page + 1
            self._result = result
            log.info("... %s posters found" % result.TotalResults)
        except:
            log.exception('')
            gutils.warning(_('No posters found for this movie.'))
            return

        if not hasattr(result, 'Item') or not len(result.Item):
            gutils.warning(_('No posters found for this movie.'))
            return

        if len(result.Item) == 1:
            o_title = self.widgets['movie']['o_title'].get_text().decode('utf-8')
            if o_title == result.Item[0].ItemAttributes.Title or keyword == result.Item[0].ItemAttributes.Title:
                self.get_poster(self.app, result.Item[0])
                return

        # populate results window
        items = {}
        for i, item in enumerate(result.Item):
            if hasattr(item, 'LargeImage') and len(item.LargeImage.URL):
                title = item.ItemAttributes.Title
                if hasattr(item.ItemAttributes, 'ProductGroup'):
                    title = title + u' - ' + item.ItemAttributes.ProductGroup
                elif hasattr(item.ItemAttributes, 'Binding'):
                    title = title + u' - ' + item.ItemAttributes.Binding
                if hasattr(item.ItemAttributes, 'ReleaseDate'):
                    title = title + u' - ' + item.ItemAttributes.ReleaseDate[:4]
                elif hasattr(item.ItemAttributes, 'TheatricalReleaseDate'):
                    item.ItemAttributes.TheatricalReleaseDate[:4]
                if hasattr(item.ItemAttributes, 'Studio'):
                    title = title + u' - ' + item.ItemAttributes.Studio
                items[i] = title

        populate_results_window(self.app.treemodel_results, items)
        self.widgets['add']['b_get_from_web'].set_sensitive(False) # disable movie plugins (result window is shared)
        self.app._resultswin_process = self.on_result_selected # use this signal (will be reverted when window is closed)
        self.widgets['results']['window'].show()
        self.widgets['results']['window'].set_keep_above(True)
Ejemplo n.º 45
0
    def toolbar_icon_clicked(self, widget, movie):
        log.info('fetching poster from MoviePosterDB.com...')
        self.movie = movie

        # correction of the movie name for the search
        o_title = None
        title = None
        if movie.o_title:
            if movie.o_title.endswith(', The'):
                o_title = u"The %s" % movie.o_title[:-5]
            else:
                o_title = movie.o_title
        if movie.title:
            if movie.title.endswith(', The'):
                title = u"The %s" % movie.title[:-5]
            else:
                title = movie.title

        # try to get an url to the large version of a poster for the movie
        # (requests are in the order:
        #  original title + year, original title only, title + year, title only)
        try:
            largeurl = None
            data = False
            if o_title:
                if movie.year:
                    url = self.baseurltitleyear % (o_title, movie.year)
                    data = self._get(url, self.widgets['window'])
                    if data and data.find('movie/0000000') < 0:
                        largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_')
                if not data or not largeurl:
                    url = self.baseurltitle % o_title
                    data = self._get(url, self.widgets['window'])
                    if data and data.find('movie/0000000') < 0:
                        largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_')
            if not data or not largeurl and title and title != o_title:
                if movie.year:
                    url = self.baseurltitleyear % (title, movie.year)
                    data = self._get(url, self.widgets['window'])
                    if data and data.find('movie/0000000') < 0:
                        largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_')
                if not data or not largeurl:
                    url = self.baseurltitle % title
                    data = self._get(url, self.widgets['window'])
                    if data and data.find('movie/0000000') < 0:
                        largeurl = gutils.trim(data, 'src=\\"', '\\"').replace('/t_', '/l_')
        except:
            log.exception('')
            gutils.warning(_('No posters found for this movie.'))
            return

        if not data or not largeurl:
            gutils.warning(_('No posters found for this movie.'))
            return

        # got the url for a large poster, fetch the data, show preview and update the
        # movie entry if the user want it
        data = self._get(largeurl, self.widgets['window'], decode=False)
        if not data:
            gutils.warning(_('No posters found for this movie.'))
            return

        if self._show_preview(data):
            update_image_from_memory(self.app, movie.number, data)