1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-17 11:30:19 +01:00

* Adding moviedb project.

This commit is contained in:
2006-11-25 08:10:43 +00:00
commit e3684f44ea
6 changed files with 3253 additions and 0 deletions

2326
glade/moviedb.glade Normal file

File diff suppressed because it is too large Load Diff

BIN
img/notavail.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

927
moviedb.py Executable file
View File

@@ -0,0 +1,927 @@
#!/usr/bin/python
# -*- coding: iso8859-2 -*-
"""
MovieDB 0.7
features:
- szukanie po tytule filmu/serii
- szukanie po nazwie pliku
todo:
- dodatkowe pozycje w menu w zale<6C>no<6E>ci od uprawnie<69>
- edycja plik<69>w
- edycja tytu<74><75>w
- edycja innych rzeczy
"""
# TODO: doda<64> okna/dialogi dodawania/edycji tytu<74>u + menu kontekstowe
# TODO: doda<64> okna/dialogi dodawania/edycji pliku + menu kontekstowe
# TODO: dodac tablic<69> w bazie, s<>ownikuj<75>c<EFBFBD> plyty_asarray, lang (sub, dub), nazwy alternatywne triggery do nich
# TODO: opanowa<77> dodawanie/usuwanie pozycji w menu g<><67>wnego
#{{{ podstawowe importy i sprawdzenia
import sys
import os
WRKDIR = sys.argv[0:][0].split('moviedb.py')[0]
if WRKDIR[0] != '/':
"""<EFBFBD>cie<EFBFBD>ka nie jest absolutna"""
WRKDIR = os.getcwd()+"/"+WRKDIR
try:
import pygtk
#tell pyGTK, if possible, that we want GTKv2
pygtk.require("2.0")
except:
#Some distributions come with GTK2, but not pyGTK
pass
try:
import gtk
import gtk.glade
except:
print "You need to install pyGTK or GTKv2 ",
print "or set your PYTHONPATH correctly."
print "try: export PYTHONPATH=",
print "/usr/local/lib/python2.2/site-packages/"
sys.exit(1)
#now we have both gtk and gtk.glade imported
#Also, we know we are running GTK v2
try:
from pyPgSQL import PgSQL
except:
print "You need to install pyPgSQL to run this app\nhttp://pypgsql.sourceforge.net/"
sys.exit(1)
try:
import pyExcelerator
except:
print "You need pyExcelerator\nhttp://sourceforge.net/projects/pyexcelerator"
sys.exit(1)
#}}}
try:
path = os.environ['HOME']
except:
path = "/tmp"
try:
# przeczytaj plik, o ile istnieje
f = open("%s/.moviedb" % path,"rw")
zpliku = f.read()
f.close()
p = {}
zpliku = zpliku.split("\n")
for i in zpliku:
i = i.split("\t")
p[i[0]] = i[1]
if len(p) == 5:
USER=p['user']
PASS=p['pass']
HOST=p['host']
DB=p['db']
CD=p['cdrom']
else:
USER="movie"
PASS="teamsleep"
HOST="localhost"
DB="moviedb"
CD="/mnt/cdrom"
except:
# w przeciwnym przypadku przjmij warto<74>ci domy<6D>lne
USER="movie"
PASS="teamsleep"
HOST="localhost"
DB="moviedb"
CD="/mnt/cdrom"
class SaveAsMDB:
"""pokazuje dialog zapisu(exportu) do pliku""" #{{{
def __init__(self):
self.gladefile = WRKDIR + "/glade/moviedb.glade"
def run(self):
self.savegld = gtk.glade.XML(self.gladefile, "saveasMDB")
self.save = self.savegld.get_widget("saveasMDB")
self.savegld.get_widget("saveasMDB")
self.save.set_do_overwrite_confirmation(True)
self.save.set_title("MovieDB - Save as...")
uri = self.save.set_current_name("moviedb.xls")
self.result = self.save.run()
uri = self.save.get_uri()
self.save.destroy()
return self.result,uri
#}}}
class SelectFolderMDB:
"""pokazuje dialog wskazania katalogu""" #{{{
def __init__(self):
self.gladefile = WRKDIR + "/glade/moviedb.glade"
def run(self):
self.selgld = gtk.glade.XML(self.gladefile, "selectFolderMDB")
self.sel = self.selgld.get_widget("selectFolderMDB")
self.sel.set_title("MovieDB - Select folder")
self.result = self.sel.run()
uri = self.sel.get_uri()
print uri
self.sel.destroy()
return self.result,uri
#}}}
class PrefsMDB:
"""ustawia i zapisuje do pliku ~/.moviedb informacje zwi<77>zane z aplikacj<63>""" #{{{
def __init__(self):
self.prefs = {}
self.gladefile = WRKDIR + "/glade/moviedb.glade"
self.wPrefs = gtk.glade.XML(self.gladefile,"Prefs")
self.wPrefs.get_widget("dbuser").set_text(USER)
self.wPrefs.get_widget("dbpass").set_text(PASS)
self.wPrefs.get_widget("dbhost").set_text(HOST)
self.wPrefs.get_widget("dbname").set_text(DB)
self.wPrefs.get_widget("devdev").set_text(CD)
dic = {"on_prefsCancel_clicked" :self.abandonPrefs,\
"on_prefsSave_clicked" :self.savePrefs,\
"on_selectFolder_clicked" :self.chooseDir}
# pod<6F><64>czenie sygna<6E><61>w
self.wPrefs.signal_autoconnect(dic)
def abandonPrefs(self, widget):
"""porzu<EFBFBD> edycj<63> preferencji"""
self.wPrefs.get_widget("Prefs").destroy()
def savePrefs(self,widget):
"""zapisz ustawienia"""
self.prefs["user"] = self.wPrefs.get_widget("dbuser").get_text()
self.prefs["pass"] = self.wPrefs.get_widget("dbpass").get_text()
self.prefs["host"] = self.wPrefs.get_widget("dbhost").get_text()
self.prefs["db"] = self.wPrefs.get_widget("dbname").get_text()
self.prefs["cdrom"] = self.wPrefs.get_widget("devdev").get_text()
try:
f = open("%s/.moviedb" % path,"w")
f.write("user\t" + self.prefs['user']\
+ "\npass\t" + self.prefs['pass']\
+ "\nhost\t" + self.prefs['host']\
+ "\ndb\t" + self.prefs['db']\
+ "\ncdrom\t" + self.prefs['cdrom']\
)
f.close()
except:
print "Nie mo<6D>na zapisa<73> ustawie<69>!"
# uaktualnij zmienne
USER=self.prefs['user']
PASS=self.prefs['pass']
HOST=self.prefs['host']
DB=self.prefs['db']
CD=self.prefs["cdrom"]
self.wPrefs.get_widget("Prefs").destroy()
def chooseDir(self,widget):
"""wska<EFBFBD> katalog ustawienia"""
sel = SelectFolderMDB()
result,selected = sel.run()
if selected[:8] == 'file:///':
selected = selected[7:]
self.wPrefs.get_widget("devdev").set_text(selected)
# uaktualnij zmienne
DB=selected
#}}}
class StdMSG:
"""pokazuje standartowy dialog - napis i jedne/dwa knefle""" #{{{
def __init__(self, title="", message="", knefli=2):
self.gladefile = WRKDIR + "/glade/moviedb.glade"
self.title = title
self.message = message
self.knefli = knefli
def run(self):
self.msgld = gtk.glade.XML(self.gladefile, "stdMSG")
self.msg = self.msgld.get_widget("stdMSG")
self.msg.set_title(self.title)
self.msgld.get_widget("message").set_markup(self.message)
if self.knefli == 1:
self.msgld.get_widget("cancelbutton2").hide()
self.result = self.msg.run()
self.msg.destroy()
return self.result
#}}}
class LoginMDB:
"""pokazuje dialog logowania""" #{{{
def __init__(self):
self.gladefile = WRKDIR + "/glade/moviedb.glade"
def run(self):
self.logingld = gtk.glade.XML(self.gladefile, "loginMDB")
self.login = self.logingld.get_widget("loginMDB")
try:
pixBuf = gtk.gdk.pixbuf_new_from_file(WRKDIR + "/pixmaps/login.png")
self.logingld.get_widget("loginImg").set_from_pixbuf(pixBuf)
except:
pass
self.login.set_title("MovieDB - Login")
self.result = self.login.run()
l = self.logingld.get_widget("flogin").get_text()
p = self.logingld.get_widget("fpass").get_text()
self.login.destroy()
return self.result,[l,p]
#}}}
class AboutMDB:
"""pokazuje prosty dialog "o programie" """ #{{{
def __init__(self):
self.gladefile = WRKDIR + "/glade/moviedb.glade"
def run(self):
self.aboutgld = gtk.glade.XML(self.gladefile, "aboutMDB")
self.about = self.aboutgld.get_widget("aboutMDB")
try:
pixBuf = gtk.gdk.pixbuf_new_from_file(WRKDIR + "/pixmaps/about.png")
self.aboutgld.get_widget("aboutImg").set_from_pixbuf(pixBuf)
except:
pass
self.about.set_title("MovieDB - About")
self.result = self.about.run()
self.about.destroy()
return self.result
#}}}
class DetailsMDB:
"""Pokazuje okno z informacjami wyci<63>gni<6E>tymi z DB na podstawie id tytu<74>u""" #{{{
def __init__(self, tid=0, perms=0):
"""innicjalizacja obiektu"""
gladefile=WRKDIR + "/glade/moviedb.glade"
self.wDetails = gtk.glade.XML(gladefile,"winDetails")
self.wDetails.get_widget("image1").set_from_file(WRKDIR + "/img/notavail.gif")
# pomocnicze zmienne
self.perms = perms
self.typ = '0'
self.imgIndeks = 1
# inicjalizacja listy z tytu<74>ami
import gobject
self.lista=self.wDetails.get_widget("pliki")
self.model=gtk.ListStore(gobject.TYPE_INT,gobject.TYPE_STRING,gobject.TYPE_STRING,\
gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,\
gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,\
gobject.TYPE_STRING, gobject.TYPE_STRING)
self.lista.set_model(self.model)
self.lista.set_headers_visible(True)
columns = [[0,"Id"],[1,u"P<EFBFBD>yta"],[2,"Nazwa pliku"],\
[3,"Sub"],[4,"Dub"],[5,"Rozdz."],\
[6,"Video"],[7,"Audio"],[8,"Q"],[9,"Rozm."],[10,'Grupa']]
for col in columns:
renderer=gtk.CellRendererText()
column=gtk.TreeViewColumn(col[1],renderer, text=col[0])
column.set_sort_column_id(col[0])
column.set_resizable(True)
if col[0] != 0:
self.lista.append_column(column)
# inicjalizacja linii statusu
self.sb=self.wDetails.get_widget("statusDet")
self.sbSearchCId = self.sb.get_context_id('detailed res')
self.sbid = 0
# g<><67>wna robota:
cx = PgSQL.connect(user=USER, password=PASS, host=HOST, database=DB, client_encoding="iso8859-2")
c = cx.cursor()
if self.perms != 2:
typ = 4
else:
typ = 0
# {{{ SQL: DetailsMDB#1 wyci<63>gni<6E>cie podstawowych informacji o tytule
c.execute("SELECT\
tytul,\
alt,\
data_wydania,\
ilosc_w_serii,\
ilosc_posiadanych,\
nazwa_rodzaju,\
data_zakonczenia,\
a.id_typu\
from\
nazwa_tytulu n\
left join tytul a using(id_tytulu)\
left join rodzaj r using(id_rodzaju)\
where\
n.id_tytulu = %s\
and a.id_typu != %s\
order by\
alt", tid,typ)
#}}}
res = c.fetchall()
# {{{ wielki shit do uzupe<70>nienia formularzyka
if len(res) != 0:
for row in res:
if row[1] == False:
# g<><67>wny tytu<74>
if row[7] == 1 or row[7] == 4:
self.typ = 'a'
else:
self.typ = 'f'
self.wDetails.get_widget("tytul").set_text(row[0].decode("iso8859-2"))
self.wDetails.get_widget("winDetails").set_title('MovieDB - '+row[0].decode("iso8859-2"))
# SQL: DetailsMDB#2 poci<63>gni<6E>cie /genre/
c.execute("select nazwa from genre_tytul a left join genre g using(id_genre) where id_tytulu=%s order by nazwa",tid)
gen = c.fetchall()
for g in gen:
if (self.wDetails.get_widget("rodzaj").get_text()) == '':
self.wDetails.get_widget("rodzaj").set_text(g[0])
else:
self.wDetails.get_widget("rodzaj").set_text(self.wDetails.get_widget("rodzaj").get_text()+", "+g[0])
if (self.wDetails.get_widget("rodzaj").get_text()) == '':
self.wDetails.get_widget("rodzaj").hide()
self.wDetails.get_widget("label17").hide()
if row[2]==None:
dadaod = 'unknown'
else:
dadaod = row[2].strftime("%Y-%m-%d")
if row[6]==None:
dadado = 'unknown'
else:
dadado = row[6].strftime("%Y-%m-%d")
if dadaod == dadado:
self.wDetails.get_widget("label15").set_markup("<b>Data wydania:</b>")
self.wDetails.get_widget("data").set_text(dadaod)
else:
self.wDetails.get_widget("data").set_text(dadaod+"/"+dadado)
if row[5] != None:
self.wDetails.get_widget("kategoria").set_text(row[5])
else:
self.wDetails.get_widget("kategoria").hide()
self.wDetails.get_widget("label12").hide()
if row[3] != None:
self.wDetails.get_widget("ilEpizodow").set_text("%d" % row[3])
else:
self.wDetails.get_widget("ilEpizodow").hide()
self.wDetails.get_widget("label13").hide()
if row[4] != None:
self.wDetails.get_widget("ilPosEpis").set_text("%d" % row[4])
else:
self.wDetails.get_widget("ilPosEpis").hide()
self.wDetails.get_widget("label16").hide()
else:
# tytu<74>y s<> tytu<74>ami alternatywnymi
if (self.wDetails.get_widget("tytAlt").get_text()) == '':
self.wDetails.get_widget("tytAlt").set_text(row[0].decode("iso8859-2"))
else:
self.wDetails.get_widget("tytAlt").set_text(self.wDetails.get_widget("tytAlt").get_text()+",\n"+row[0].decode("iso8859-2"))
# sprawd<77> czy tutu<74>y alternatywne s<> puste, je<6A>li tak, ukryj.
if(self.wDetails.get_widget("tytAlt").get_text()) == '':
self.wDetails.get_widget("label11").hide()
self.wDetails.get_widget("tytAlt").hide()
#}}}
# {{{ opanuj obrazki:
try:
pixBuf = gtk.gdk.pixbuf_new_from_file(WRKDIR + "/img/%c%d_1.jpg" % (self.typ,tid))
self.wDetails.get_widget("image1").set_from_pixbuf(pixBuf)
# pod<6F><64>cz sygna<6E>y do guzik<69>w, wy<77><79>cznie w przypadku istnienia obrazk<7A>w
# "on button1_clicked" : (self.button1_clicked, arg1,arg2)
lista = {"on_popBut_clicked" : (self.prevPict, self.typ, tid),\
"on_nasBut_clicked" : (self.nextPict, self.typ, tid)}
self.wDetails.signal_autoconnect(lista)
except:
self.wDetails.get_widget("image1").set_from_file(WRKDIR + "/img/notavail.gif")
self.wDetails.get_widget("nasBut").hide()
self.wDetails.get_widget("popBut").hide()
self.wDetails.get_widget("hseparator1").hide()
#}}}
# {{{ poka<6B> list<73> plik<69>w
c = cx.cursor()
# SQL: DetailsMDB#3 poka<6B> list<73> plik<69>w
c.execute("SELECT\
p.id_pliku,\
aktywny,\
nazwa_pliku,\
format,\
rozdz,\
vcodec,\
acodec,\
rozmiar,\
jakosc,\
nr_plyty,\
nr_pudelka,\
lang_asarray(p.id_pliku::text,'sub'::text),\
lang_asarray(p.id_pliku::text,'dub'::text),\
gp.short\
from\
plik p\
left join plyta y using(id_pliku)\
left join grupa_plik g using(id_pliku)\
left join grupa gp using(id_grupy)\
where\
id_tytulu=%s", tid)
res = c.fetchall()
# pokazanie lio<69>ci wynik<69>w a linii stratusu
if self.sbid != 0:
"""je<EFBFBD>li jest jaki<6B> mesed<65>, usu<73> go"""
self.sb.remove(self.sbSearchCId, self.sbid)
liczba_wynikow = u"Ilo<EFBFBD><EFBFBD> plik<69>w nale<6C><65>cych do tytu<74>u: %d" % len(res)
self.sbid = self.sb.push(self.sbSearchCId, liczba_wynikow)
if len(res)>0:
# pokazanie listy
self.model.clear()
for i in res:
self.insert_row(self.model,i[0],"%s/%s" % (i[9],i[10]),i[2].decode("iso8859-2"),i[11],i[12],i[4],i[5],i[6],i[8],i[7],i[13])
#model.set_sort_column_id(1,gtk.SORT_ASCENDING)
#}}}
# SYGNA<4E>Y
def prevPict(self, widget, typ, tid):
"""poka<EFBFBD> poprzedni obrazek, je<6A>li jest"""
if self.imgIndeks > 1:
self.imgIndeks-=1
try:
pixBuf = gtk.gdk.pixbuf_new_from_file(WRKDIR + "/img/%c%d_%d.jpg" % (typ,tid,self.imgIndeks))
self.wDetails.get_widget("image1").clear()
self.wDetails.get_widget("image1").set_from_pixbuf(pixBuf)
except:
pass
def nextPict(self, widget, typ, tid):
"""poka<EFBFBD> kolejny obrazek, je<6A>li jest"""
if self.imgIndeks < 5:
self.imgIndeks+=1
try:
pixBuf = gtk.gdk.pixbuf_new_from_file(WRKDIR + "/img/%c%d_%d.jpg" % (typ,tid,self.imgIndeks))
self.wDetails.get_widget("image1").clear()
self.wDetails.get_widget("image1").set_from_pixbuf(pixBuf)
except:
pass
# funkcje pomocnicze
def insert_row(self,model,pid,plyta,nazwa_pliku,sub,dub,rozdz,vid,aud,q,rozm,grup):
myiter=model.insert_after(None,None)
model.set_value(myiter,0,pid)
model.set_value(myiter,1,plyta)
model.set_value(myiter,2,nazwa_pliku)
model.set_value(myiter,3,sub)
model.set_value(myiter,4,dub)
model.set_value(myiter,5,rozdz)
model.set_value(myiter,6,vid)
model.set_value(myiter,7,aud)
model.set_value(myiter,8,q)
model.set_value(myiter,9,rozm)
model.set_value(myiter,10,grup)
#}}}
class MovieDB:
"""pokazuj<EFBFBD>ca g<><67>wne okno aplikacji, pozwalaj<61>ca na przeszukiwanie w<>r<EFBFBD>d plik<69>w i tytu<74><75>w i wy<77>wietlaj<61>ca wynik wyszukiwania""" #{{{
def __init__(self, perms=0):
self.perms = perms
self.gladefile=WRKDIR + "/glade/moviedb.glade"
self.wTree=gtk.glade.XML(self.gladefile,"mainWin")
# sygna<6E>y:
dic = {"on_mainWin_destroy" :(gtk.main_quit),\
"on_quit1_activate" :(gtk.main_quit),\
"on_szukaj_clicked" :(self.searchdb,self.perms),\
"on_szukPat_activate" :(self.searchdb,self.perms),\
"on_lista_row_activated" :(self.szczegoly,self.perms),\
"on_about1_activate" :self.oprogramie,\
"on_cut1_activate" :self.showPrefs,\
"on_save_as1_activate" :self.exportToXLS}
# inicjalizacja dodatkowych pozycji w menu, je<6A>li uprawnienia pozwalaj<61>
if self.perms == 2:
pass
#self.wTree.get_widget("mainMenu").
# pod<6F><64>czenie sygna<6E><61>w
self.wTree.signal_autoconnect(dic)
# inicjalizacja combo box<6F>w
self.treeview=self.wTree.get_widget("pattMatch").set_active(0)
self.treeview=self.wTree.get_widget("typ").set_active(0)
if self.perms ==2:
self.treeview=self.wTree.get_widget("typ").append_text('XXX')
# inicjalizacja listy z tytu<74>ami
import gobject
self.treeview=self.wTree.get_widget("lista")
self.treemodel=gtk.TreeStore(gobject.TYPE_INT,gobject.TYPE_STRING,gobject.TYPE_INT,\
gobject.TYPE_INT,gobject.TYPE_STRING,gobject.TYPE_STRING,\
gobject.TYPE_STRING)
self.treeview.set_model(self.treemodel)
self.treeview.set_headers_visible(True)
columns = [[0,"Id"],[1,u"Tytu<EFBFBD>"],[2,u"Ilo<EFBFBD><EFBFBD>"],[3,"Posiadanych"],[4,"Rok"],[5,"Typ"],[6,"Plyty"]]
for col in columns:
renderer=gtk.CellRendererText()
column=gtk.TreeViewColumn(col[1],renderer, text=col[0])
column.set_sort_column_id(col[0])
column.set_resizable(True)
if col[0] != 0:
self.treeview.append_column(column)
# inicjalizacja linii statusu
self.sb=self.wTree.get_widget("statusbar")
self.sbSearchCId = self.sb.get_context_id('search res')
self.sbid = 0
return
def insert_row(self,model,parent,tid,tytul,il,pos,rok,typ,plyty):
myiter=model.insert_after(parent,None)
model.set_value(myiter,0,tid)
model.set_value(myiter,1,tytul)
model.set_value(myiter,2,il)
model.set_value(myiter,3,pos)
model.set_value(myiter,4,rok)
model.set_value(myiter,5,typ)
model.set_value(myiter,6,plyty)
return myiter
#####CALLBACKS
def szczegoly(self,treeview,path,view_column,perms=0):
"""poka<EFBFBD> szczeg<65><67>y w nowym oknie.""" # {{{
win = DetailsMDB(treeview.get_model().get_value(treeview.get_model().get_iter(path),0),perms)
#}}}
def oprogramie(self, widget):
"""Pokazuje dialog about""" #{{{
about = AboutMDB()
result = about.run()
#}}}
def showPrefs(self, widget):
"""Pokazuje okno preferencji""" #{{{
prefs = PrefsMDB()
#}}}
def searchdb(self,widget,perms=0):
"""u<EFBFBD><EFBFBD><EFBFBD> zapytanie i wypluj wyniki do treeview""" #{{{
if self.wTree.get_widget("pattMatch").get_active() == 3:
pattern=self.wTree.get_widget("szukPat").get_text()
elif self.wTree.get_widget("pattMatch").get_active() == 2:
pattern="%" + self.wTree.get_widget("szukPat").get_text()
elif self.wTree.get_widget("pattMatch").get_active() == 1:
pattern=self.wTree.get_widget("szukPat").get_text() + "%"
else:
pattern="%" + self.wTree.get_widget("szukPat").get_text() + "%"
cx = PgSQL.connect(user=USER, password=PASS, host=HOST, database=DB, client_encoding="iso8859-2")
c = cx.cursor()
if self.wTree.get_widget("czalt").get_active():
klon = False
else:
klon = True
# szukaj wg typu:
# NOTE: daj tu to, co potrzeba
anime,filmy,kreskowki,xxx,typ = self.getType()
if self.wTree.get_widget("radn").get_active():
# SQL: zapytanie zbieraj<61>ce tytu<74>y film<6C>w po kluczu nazw plik<69>w
# TODO: zrobi<62> tablic<69> przechowuj<75>c<EFBFBD> nr p<>yt (najlepiej triggerze)
c.execute("SELECT distinct\
a.id_tytulu,\
n.tytul,\
alt,\
to_char (data_wydania,'YYYY'),\
case\
when\
ilosc_w_serii is null then 0\
else\
ilosc_w_serii\
end,\
case\
when\
ilosc_posiadanych is null then 0\
else\
ilosc_posiadanych\
end,\
nazwa_typu,\
plyty_asstring(a.id_tytulu::text)\
from\
nazwa_tytulu as n\
left join tytul a using(id_tytulu)\
left join typ as t using(id_typu)\
left join plik p using(id_tytulu)\
where\
(alt is false or alt is %s)\
and nazwa_pliku ilike %s\
and id_typu in (%s, %s, %s, %s)\
and id_typu != %s\
order by\
id_tytulu, alt",(klon,pattern.encode("iso8859-2"),anime,xxx,filmy,kreskowki,typ))
else:
# SQL: zapytanie zbieraj<61>ce tytu<74>y film<6C>w
c.execute("SELECT \
a.id_tytulu,\
n.tytul,\
alt,\
to_char (data_wydania,'YYYY'),\
case\
when\
ilosc_w_serii is null then 0\
else\
ilosc_w_serii\
end,\
case\
when\
ilosc_posiadanych is null then 0\
else\
ilosc_posiadanych\
end,\
nazwa_typu,\
plyty_asstring(a.id_tytulu::text)\
from\
nazwa_tytulu as n\
left join tytul a using(id_tytulu)\
left join typ as t using(id_typu)\
where\
(alt is false or alt is %s)\
and tytul ilike %s\
and id_typu in (%s, %s, %s, %s)\
and id_typu != %s\
order by\
id_tytulu, alt",(klon,pattern.encode("iso8859-2"),anime,xxx,filmy,kreskowki,typ))
res = c.fetchall()
cx.close()
# pokazanie lio<69>ci wynik<69>w a linii stratusu
if self.sbid != 0:
"""je<EFBFBD>li jest jaki<6B> mesed<65>, usu<73> go"""
self.sb.remove(self.sbSearchCId, self.sbid)
liczba_wynikow = u"Ilo<EFBFBD><EFBFBD> znalezionych rekord<72>w: %d" % len(res)
self.sbid = self.sb.push(self.sbSearchCId, liczba_wynikow)
if len(res)>0:
# pokazanie listy
model=self.treemodel
self.treemodel.clear()
if self.wTree.get_widget("showAsTree").get_active():
ido=0
for i in res:
if i[2] == True and ido == i[0]:
self.insert_row(model,iterobj,i[0],i[1].decode("iso8859-2"),i[4],i[5],i[3],i[6],i[7])
else:
iterobj = self.insert_row(model,None,i[0],i[1].decode("iso8859-2"),i[4],i[5],i[3],i[6],i[7])
ido = i[0]
else:
for i in res:
self.insert_row(model,None,i[0],i[1].decode("iso8859-2"),i[4],i[5],i[3],i[6],i[7])
#model.set_sort_column_id(1,gtk.SORT_ASCENDING)
# pokazanie wynik<69>w w tabelce
self.wTree.get_widget("scrListy").show()
self.treeview.expand_all()
else:
self.wTree.get_widget("scrListy").hide()
#}}}
def getType(self):
"""zdejmuje typ dla zapytania SQL"""
typ = self.wTree.get_widget("typ").get_active()
if typ == 4:
anime = 4
filmy = 4
kreskowki = 4
xxx = 4
elif typ == 3:
anime = 3
filmy = 3
kreskowki = 3
xxx = 3
elif typ == 2:
anime = 2
filmy = 2
kreskowki = 2
xxx = 2
elif typ == 1:
anime = 1
filmy = 1
kreskowki = 1
xxx = 1
else:
anime = 1
filmy = 2
kreskowki = 3
xxx = 4
if self.perms !=2:
typ=4
else:
typ=0
return anime,filmy,kreskowki,xxx,typ
def exportToXLS(self,widget):
"""eksportuj baz<61> do arkusza xls""" #{{{
fIter = self.treemodel.get_iter_first()
ajdiki = "(0"
if fIter!=None:
ids = []
ids.append(self.treemodel.get_value(fIter,0))
nIter = self.treemodel.iter_next(fIter)
while nIter!=None:
ids.append(self.treemodel.get_value(nIter,0))
nIter = self.treemodel.iter_next(nIter)
ajl = []
for i in set(ids):
ajl.append(i)
ajdiki+=",%s" % i
else:
pass
ajdiki+=")"
idnum = len(ajl)
sa = SaveAsMDB()
result,uri = sa.run()
if (result == gtk.RESPONSE_OK):
# open(uri[7:],"w")
import pyExcelerator as X
w = X.Workbook()
X.UnicodeUtils.DEFAULT_ENCODING = 'cp1250'
anime,filmy,kreskowki,xxx,typ = self.getType()
cx = PgSQL.connect(user=USER, password=PASS, host=HOST, database=DB, client_encoding="iso8859-2")
c = cx.cursor()
sql = "select\
p.id_pliku,\
case when nr_plyty is null then 'brak' else nr_plyty end,\
nazwa_pliku,\
rozdz,\
vcodec,\
acodec,\
jakosc,\
rozmiar,\
p.id_tytulu,\
to_char (p.data_dodania,'YYYY-MM-DD HH24:MM:SS'),\
lang_asarray(p.id_pliku::text,'dub'),\
lang_asarray(p.id_pliku::text,'sub')\
from\
plik p\
left join plyta l using(id_pliku)\
left join tytul t using(id_tytulu)\
where\
p.aktywny is true\
and\
t.id_typu in (%s, %s, %s, %s)" % (anime,filmy,kreskowki,xxx)
sql+=" and\
t.id_typu != %s" % typ
sql+=" and\
p.id_tytulu in ("+ ", ".join(["%s"] * idnum) + ")\
order by\
nazwa_pliku"
c.execute(sql, ajl)
pliki = c.fetchall()
row = 0
sheet = w.add_sheet("Anime")
# nag<61><67>wki
sheet.write(row, 0, u"tytu<EFBFBD> anime".encode("cp1250"))
sheet.write(row, 1, u"nr p<>yty".encode("cp1250"))
sheet.write(row, 2, "nazwa pliku".encode("cp1250"))
sheet.write(row, 3, "dub".encode("cp1250"))
sheet.write(row, 4, "sub".encode("cp1250"))
sheet.write(row, 5, "rozdz".encode("cp1250"))
sheet.write(row, 6, "vcodec".encode("cp1250"))
sheet.write(row, 7, "acodec".encode("cp1250"))
sheet.write(row, 8, u"jako<EFBFBD><EFBFBD>".encode("cp1250"))
sheet.write(row, 9, "rozmiar pliku".encode("cp1250"))
sheet.write(row, 10, "typ".encode("cp1250"))
sheet.write(row, 11, "data".encode("cp1250"))
sheet.write(row, 12, u"ilo<EFBFBD><EFBFBD> odc.".encode("cp1250"))
sheet.write(row, 13, u"ilo<EFBFBD><EFBFBD> posiadanych".encode("cp1250"))
sheet.write(row, 14, "data dodania pliku".encode("cp1250"))
row+=1
idanime="0"
for plik in pliki:
if plik[9]!=idanime:
sql="SELECT\
tytul,\
alt,\
nazwa_rodzaju,\
case when data_wydania is null then 'brak' else to_char (data_wydania,'YYYY-MM-DD') end,\
data_zakonczenia,\
ilosc_w_serii,\
ilosc_posiadanych\
from\
nazwa_tytulu as n\
left join tytul a using(id_tytulu)\
left join rodzaj r using(id_rodzaju)\
where\
a.id_tytulu=%s\
and\
a.id_typu in (%s, %s, %s, %s)\
and\
a.id_typu != %s\
and\
alt is false\
order by\
tytul" % (plik[8],anime,filmy,kreskowki,xxx,typ)
c.execute(sql)
tytuly = c.fetchone()
print tytuly[0]
sheet.write(row, 0, tytuly[0].decode("iso8859-2").encode("cp1250"))
sheet.write(row, 1, plik[1].encode("cp1250"))
sheet.write(row, 2, plik[2].decode("iso8859-2").encode("cp1250"))
sheet.write(row, 3, plik[10].encode("cp1250"))
sheet.write(row, 4, plik[11].encode("cp1250"))
sheet.write(row, 5, plik[3].encode("cp1250"))
sheet.write(row, 6, plik[4].encode("cp1250"))
sheet.write(row, 7, plik[5].encode("cp1250"))
sheet.write(row, 8, plik[6])
sheet.write(row, 9, plik[7])
sheet.write(row, 10, "typ".encode("cp1250"))
sheet.write(row, 11, tytuly[3])
sheet.write(row, 12, tytuly[5])
sheet.write(row, 13, tytuly[6])
sheet.write(row, 14, plik[9].encode("cp1250"))
row+=1
w.save(uri[7:])
cx.close()
#}}}
#}}}
# NOTE: koniec deklaracji klas. g<><67>wny program:
petla = 0
perms = 0
while petla == 0:
# {{{ pokazanie dialogu logowania w p<>tli
login = LoginMDB()
result,loginPair = login.run()
#sprawdzenie co te<74> u<>ytkownik wpisa<73> i dokonanie odpowiedniego zachowania
if (result == gtk.RESPONSE_OK):
# w przypadku naci<63>ni<6E>cia OK, pobranie z DB uprawnienia, je<6A>li login/has<61>o si<73> zgadza
cx = PgSQL.connect(user=USER, password=PASS, host=HOST, database=DB, client_encoding="iso8859-2")
c = cx.cursor()
c.execute("SELECT\
uprawnienia\
from\
users\
where\
login = %s\
and password = md5(%s)\
", loginPair[0],loginPair[1])
perms = c.fetchone()
cx.close()
if perms==None:
# z<>y login lub has<61>o
m = StdMSG(u"MovieDB - B<><42>d logowania",u"Nieprawid<EFBFBD>owy login lub has<61>o.\n",1)
m.run()
else:
# zapytanie zwr<77>ci<63>o nie None; wychodzimy z p<>tli while.
petla = 1
perms = perms[0]
elif (result == gtk.RESPONSE_CANCEL):
# user nacisn<73><6E> cancel, wi<77>c nie chce, lub ne mo<6D>e si<73> zalogowa<77>. sprawdzamy jak jest.
# pokazanie dialogu z pytaniem
m = StdMSG("MovieDB - Pytanie",u"Jeste<EFBFBD> pewien, <20>e <b>nie chcesz</b> si<73> logowa<77>?\n")
res = m.run()
if(res == gtk.RESPONSE_OK):
# je<6A>li jest pewny, wychodzimy z p<>tli while. je<6A>li nie, nic nie robimy,
# okno logowanie pojawi si<73> przy powt<77>rnym obrocie p<>tli.
petla = 1
else:
# user ubi<62> okno logowania, lub poci<63>gn<67><6E> z krzy<7A>a, lub do dialogu zosta<74> wys<79>any inny sygna<6E>.
petla = 2
#}}}
if petla != 2:
# w przypadku poci<63>gni<6E>cia z krzy<7A>a wychodzimy z aplikacji, w pozosta<74>ych przypadkach uruchomione zostaje g<><67>wne okno.
app=MovieDB(perms)
try:
gtk.main()
except KeyboardInterrupt:
gtk.main_quit

BIN
pixmaps/about.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
pixmaps/ikona.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
pixmaps/login.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB