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

* Added function responsible for opening and saving database.

* Improvements in hundred places.
This commit is contained in:
2006-12-07 16:54:37 +00:00
parent 2431521daf
commit 1a308f586c

View File

@@ -348,26 +348,27 @@ Public License instead of this License.
""" """
#}}} #}}}
__version__ = "0.3" __version__ = "0.5"
import sys import sys
import os import os
import mimetypes import mimetypes
import popen2 import popen2
import datetime
import bz2
import pygtk import pygtk
import gtk import gtk
import gtk.glade import gtk.glade
from pysqlite2 import dbapi2 as sqlite
from config import Config from config import Config
import deviceHelper import deviceHelper
import filetypeHelper import filetypeHelper
import dialogs import dialogs
from preferences import Preferences from preferences import Preferences
from files import fileObj
import db import db
_count=0
class PyGTKtalog: class PyGTKtalog:
def __init__(self): def __init__(self):
""" init""" """ init"""
@@ -375,6 +376,9 @@ class PyGTKtalog:
self.conf = Config() self.conf = Config()
self.conf.load() self.conf.load()
self.opened_catalog = None
self.db_tmp_filename = None
self.gladefile = "glade/main.glade" self.gladefile = "glade/main.glade"
self.pygtkcat = gtk.glade.XML(self.gladefile,"main") self.pygtkcat = gtk.glade.XML(self.gladefile,"main")
@@ -398,6 +402,7 @@ class PyGTKtalog:
'cut1','copy1','paste1','delete1','add_cd','add_directory1', 'cut1','copy1','paste1','delete1','add_cd','add_directory1',
'tb_save','tb_addcd','tb_find' 'tb_save','tb_addcd','tb_find'
) )
for w in self.widgets: for w in self.widgets:
a = self.pygtkcat.get_widget(w) a = self.pygtkcat.get_widget(w)
a.set_sensitive(False) a.set_sensitive(False)
@@ -418,6 +423,9 @@ class PyGTKtalog:
else: else:
self.statusprogress.hide() self.statusprogress.hide()
# main tree
self.discs = self.pygtkcat.get_widget('discs')
self.discs.append_column(gtk.TreeViewColumn('filename',gtk.CellRendererText(), text=1))
# window size # window size
a = self.pygtkcat.get_widget('hpaned1') a = self.pygtkcat.get_widget('hpaned1')
@@ -426,7 +434,7 @@ class PyGTKtalog:
a.set_position(self.conf.confd['v']) a.set_position(self.conf.confd['v'])
self.window.resize(self.conf.confd['wx'],self.conf.confd['wy']) self.window.resize(self.conf.confd['wx'],self.conf.confd['wy'])
# sygnały: # signals:
dic = {"on_main_destroy_event" :self.doQuit, dic = {"on_main_destroy_event" :self.doQuit,
"on_quit1_activate" :self.doQuit, "on_quit1_activate" :self.doQuit,
"on_tb_quit_clicked" :self.doQuit, "on_tb_quit_clicked" :self.doQuit,
@@ -439,6 +447,13 @@ class PyGTKtalog:
"on_properties1_activate" :self.preferences, "on_properties1_activate" :self.preferences,
"on_status_bar1_activate" :self.toggle_status_bar, "on_status_bar1_activate" :self.toggle_status_bar,
"on_toolbar1_activate" :self.toggle_toolbar, "on_toolbar1_activate" :self.toggle_toolbar,
"on_save1_activate" :self.save,
"on_tb_save_clicked" :self.save,
"on_save_as1_activate" :self.save_as,
"on_tb_open_clicked" :self.opendb,
"on_open1_activate" :self.opendb,
"on_discs_cursor_changed" :None,
"on_files_cursor_changed" :None,
} }
# connect signals # connect signals
@@ -446,6 +461,187 @@ class PyGTKtalog:
self.window.connect("delete_event", self.deleteEvent) self.window.connect("delete_event", self.deleteEvent)
#}}} #}}}
def opendb(self,widget):
"""open dtatabase file, decompress it to temp"""
#{{{
try:
if self.unsaved_project:
if self.conf.confd['confirmabandon']:
obj = dialogs.Qst('Unsaved data - pyGTKtalog','There is not saved database\nDo you really want to abandon it?')
if not obj.run():
return
except AttributeError:
pass
#create filechooser dialog
dialog = gtk.FileChooserDialog(
title="Open catalog",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN,
gtk.RESPONSE_OK
)
)
dialog.set_default_response(gtk.RESPONSE_OK)
f = gtk.FileFilter()
f.set_name("Catalog files")
f.add_pattern("*.pgt")
dialog.add_filter(f)
f = gtk.FileFilter()
f.set_name("All files")
f.add_pattern("*.*")
dialog.add_filter(f)
response = dialog.run()
tmp = self.opened_catalog
try:
self.opened_catalog = dialog.get_filename()
except:
self.opened_catalog = tmp
pass
dialog.destroy()
if response == gtk.RESPONSE_OK:
# delete an existing temp file
try:
os.unlink(self.db_tmp_filename)
except:
pass
# initial switches
self.db_tmp_filename = None
self.active_project = True
self.unsaved_project = False
self.window.set_title("untitled - pyGTKtalog")
self.db_tmp_filename = "/tmp/pygtktalog%d.db" % datetime.datetime.now().microsecond
source = bz2.BZ2File(self.opened_catalog, 'rb')
destination = open(self.db_tmp_filename, 'wb')
while True:
try:
data = source.read(1024000)
except:
dialogs.Err("Error opening file - pyGTKtalog","Cannot open file %s." % self.opened_catalog)
self.opened_catalog = None
self.newDB(self.window)
return
if not data: break
destination.write(data)
destination.close()
source.close()
self.active_project = True
self.unsaved_project = False
self.con = sqlite.connect("%s" % self.db_tmp_filename, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
self.cur = self.con.cursor()
self.window.set_title("%s - pyGTKtalog" % self.opened_catalog)
for w in self.widgets:
try:
a = self.pygtkcat.get_widget(w)
a.set_sensitive(True)
except:
pass
# PyGTK FAQ entry 23.20
while gtk.events_pending():
gtk.main_iteration()
self.__display_main_tree()
else:
self.opened_catalog = tmp
#}}}
def __create_database(self,filename):
"""make all necessary tables in db file"""
#{{{
self.con = sqlite.connect("%s" % filename, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
#self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
self.cur = self.con.cursor()
self.cur.execute("create table files(id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT, date timestamp, size integer, type integer);")
self.cur.execute("create table files_connect(id INTEGER PRIMARY KEY AUTOINCREMENT, parent numeric, child numeric, depth numeric);")
self.cur.execute("insert into files values(1, 'root', 0, 0, 0);")
self.cur.execute("insert into files_connect values(1, 1, 1, 0);")
#}}}
def save(self,widget):
"""save database to file. compress it with gzip"""
#{{{
if self.opened_catalog == None:
self.save_as(widget)
else:
self.__compress_and_save(self.opened_catalog)
#}}}
def save_as(self,widget):
"""save database to another file. compress it with gzip"""
#{{{
dialog = gtk.FileChooserDialog(
title="Save catalog as...",
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(
gtk.STOCK_CANCEL,
gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE,
gtk.RESPONSE_OK
)
)
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SAVE)
dialog.set_default_response(gtk.RESPONSE_OK)
dialog.set_do_overwrite_confirmation(True)
if widget.get_name() == 'save1':
dialog.set_title('Save catalog to file...')
f = gtk.FileFilter()
f.set_name("Catalog files")
f.add_pattern("*.pgt")
dialog.add_filter(f)
f = gtk.FileFilter()
f.set_name("All files")
f.add_pattern("*.*")
dialog.add_filter(f)
response = dialog.run()
if response == gtk.RESPONSE_OK:
filename = dialog.get_filename()
if filename[-4] == '.':
if filename[-3:].lower() != 'pgt':
filename = filename + '.pgt'
else:
filename = filename[:-3] + 'pgt'
else:
filename = filename + '.pgt'
self.__compress_and_save(filename)
self.opened_catalog = filename
dialog.destroy()
#}}}
def __compress_and_save(self,filename):
"""compress and save temporary file to catalog"""
#{{{
source = open(self.db_tmp_filename, 'rb')
destination = bz2.BZ2File(filename, 'w')
while True:
data = source.read(1024000)
if not data: break
destination.write(data)
destination.close()
source.close()
self.window.set_title("%s - pyGTKtalog" % filename)
self.unsaved_project = False
#}}}
def toggle_toolbar(self,widget): def toggle_toolbar(self,widget):
"""toggle visibility of toolbar bar""" """toggle visibility of toolbar bar"""
#{{{ #{{{
@@ -504,6 +700,16 @@ class PyGTKtalog:
pass pass
self.storeSettings() self.storeSettings()
gtk.main_quit() gtk.main_quit()
try:
self.con.commit()
self.cur.close()
self.con.close()
except:
pass
try:
os.unlink(self.db_tmp_filename)
except:
pass
return False return False
#}}} #}}}
@@ -532,20 +738,28 @@ class PyGTKtalog:
while gtk.events_pending(): while gtk.events_pending():
gtk.main_iteration() gtk.main_iteration()
#self.details.set_sensitive(True) # Create new database
#self.details.destroy() if self.db_tmp_filename!=None:
self.con.commit()
self.cur.close()
self.con.close()
os.unlink(self.db_tmp_filename)
self.db_tmp_filename = datetime.datetime.now()
self.db_tmp_filename = "/tmp/pygtktalog%d.db" % self.db_tmp_filename.microsecond
self.__create_database(self.db_tmp_filename)
#self.details = gtk.Button("Press mi or daj"); #clear treeview, if possible
#self.details.set_name("details") try:
self.discs.get_model().clear()
except:
pass
#self.detailplaceholder.add_with_viewport(self.details)
#self.details.show()
return
#}}} #}}}
def deleteEvent(self, widget, event, data=None): def deleteEvent(self, widget, event, data=None):
"""checkout actual database changed. If so, do the necessary ask.""" """checkout actual database changed. If so, do the necessary ask."""
#{{{ check if any unsaved project is on go. #{{{
try: try:
if self.unsaved_project: if self.unsaved_project:
if self.conf.confd['confirmquit']: if self.conf.confd['confirmquit']:
@@ -555,6 +769,18 @@ class PyGTKtalog:
except AttributeError: except AttributeError:
pass pass
self.storeSettings() self.storeSettings()
try:
self.cur.close()
except:
pass
try:
self.con.close()
except:
pass
try:
os.unlink(self.db_tmp_filename)
except:
pass
return False return False
#}}} #}}}
@@ -570,7 +796,8 @@ class PyGTKtalog:
#{{{ #{{{
obj = dialogs.PointDirectoryToAdd() obj = dialogs.PointDirectoryToAdd()
res = obj.run() res = obj.run()
self.scan(res[1],res[0]) if res !=(None,None):
self.__scan(res[1],res[0])
#}}} #}}}
def addCD(self,widget): def addCD(self,widget):
@@ -583,9 +810,7 @@ class PyGTKtalog:
label = obj.run() label = obj.run()
if label != None: if label != None:
self.scan(self.conf.confd['cd'],label) self.__scan(self.conf.confd['cd'],label)
self.unsaved_project = True
# umount/eject cd # umount/eject cd
if self.conf.confd['eject']: if self.conf.confd['eject']:
@@ -600,39 +825,56 @@ class PyGTKtalog:
dialogs.Wrn("error mounting device - pyGTKtalog","Cannot mount device pointed to %s.\nLast mount message:\n<tt>%s</tt>" % (self.conf.confd['cd'],mount)) dialogs.Wrn("error mounting device - pyGTKtalog","Cannot mount device pointed to %s.\nLast mount message:\n<tt>%s</tt>" % (self.conf.confd['cd'],mount))
#}}} #}}}
def scan(self,path,label): def __scan(self,path,label,currentdb=None):
"""scan content of the given path""" """scan content of the given path"""
#{{{ #{{{
global _count
_count= 0
mime = mimetypes.MimeTypes() mime = mimetypes.MimeTypes()
mov_ext = ('mkv','avi','ogg','mpg','wmv','mp4','mpeg') mov_ext = ('mkv','avi','ogg','mpg','wmv','mp4','mpeg')
img_ext = ('jpg','jpeg','png','gif','bmp','tga','tif','tiff','ilbm','iff','pcx') img_ext = ('jpg','jpeg','png','gif','bmp','tga','tif','tiff','ilbm','iff','pcx')
# count files in directory tree # count files in directory tree
count = 0 count = 0
if self.sbid != 0:
self.status.remove(self.sbSearchCId, self.sbid)
self.sbid = self.status.push(self.sbSearchCId, "Calculating number of files in directory tree...")
for root,kat,plik in os.walk(path): for root,kat,plik in os.walk(path):
for p in plik: for p in plik:
count+=1 count+=1
while gtk.events_pending(): gtk.main_iteration()
frac = 1.0/count frac = 1.0/count
count = 1
def recurse(path,name,wobj,date=0,frac=0): self.count = 0
"""recursive scans the path"""
def __recurse(path,name,wobj,date=0,frac=0,idWhere=1):
"""recursive scans the path
path = path string
name = field name
wobj = obiekt katalogu
date = data pliku
frac - kolejne krok w statusbarze.
idWhere - simple id parent, or "place" where to add node
"""
#{{{ #{{{
global _count
walker = os.walk(path) walker = os.walk(path)
root,dirs,files = walker.next() root,dirs,files = walker.next()
ftype = 1
self.cur.execute("insert into files(filename, date, size, type) values(?,?,?,?)",(name, date, 0, ftype))
self.cur.execute("select seq FROM sqlite_sequence WHERE name='files'")
currentid=self.cur.fetchone()[0]
self.cur.execute("insert into files_connect(parent,child,depth) values(?,?,?)",(currentid, currentid, 0))
f = fileObj(name=name,filetype="d",mtime=date) if idWhere>0:
self.cur.execute("insert into files_connect(parent, child, depth) select r1.parent, r2.child, r1.depth + r2.depth + 1 as depth FROM files_connect r1, files_connect r2 WHERE r1.child = ? AND r2.parent = ? ",(idWhere, currentid))
for i in dirs: for i in dirs:
f.add_member(recurse(os.path.join(path,i),i,wobj,os.stat(os.path.join(root,i)).st_mtime,frac)) st = os.stat(os.path.join(root,i))
__recurse(os.path.join(path,i),i,wobj,st.st_mtime,frac,currentid)
for i in files: for i in files:
_count+=1 self.count = self.count + 1
st = os.stat(os.path.join(root,i)) st = os.stat(os.path.join(root,i))
### scan files ### scan files
if i[-3:].lower() in mov_ext or \ if i[-3:].lower() in mov_ext or \
mime.guess_type(i)!= (None,None) and \ mime.guess_type(i)!= (None,None) and \
@@ -644,23 +886,28 @@ class PyGTKtalog:
mime.guess_type(i)[0].split("/")[0] == 'image': mime.guess_type(i)[0].split("/")[0] == 'image':
pass pass
### end of scan ### end of scan
# progress/status
if wobj.sbid != 0: if wobj.sbid != 0:
wobj.status.remove(wobj.sbSearchCId, wobj.sbid) wobj.status.remove(wobj.sbSearchCId, wobj.sbid)
wobj.sbid = wobj.status.push(wobj.sbSearchCId, "Scannig: %s" % (os.path.join(root,i))) wobj.sbid = wobj.status.push(wobj.sbSearchCId, "Scannig: %s" % (os.path.join(root,i)))
wobj.progress.set_fraction(frac * self.count)
wobj.progress.set_fraction(frac * _count)
# PyGTK FAQ entry 23.20 # PyGTK FAQ entry 23.20
while gtk.events_pending(): gtk.main_iteration() while gtk.events_pending(): gtk.main_iteration()
f.add_member(fileObj(name=i, size=st.st_size, filetype="r", mtime=st.st_mtime)) self.cur.execute('insert into files(filename, date, size, type) values(?,?,?,?)',(i, st.st_mtime, st.st_size,2))
self.cur.execute("select seq FROM sqlite_sequence WHERE name='files'")
return f currentfileid=self.cur.fetchone()[0]
self.cur.execute("insert into files_connect(parent,child,depth) values(?,?,?)",(currentfileid, currentfileid, 0))
if currentid>0:
self.cur.execute("insert into files_connect(parent, child, depth) select r1.parent, r2.child, r1.depth + r2.depth + 1 as depth FROM files_connect r1, files_connect r2 WHERE r1.child = ? AND r2.parent = ? ",(currentid, currentfileid))
self.con.commit()
#}}} #}}}
fileobj = recurse(path,label,self,0,frac) self.con.commit()
baza = db.dbfile() fileobj = __recurse(path,label,self,0,frac)
baza.populate(fileobj) self.unsaved_project = True
self.__display_main_tree()
if self.sbid != 0: if self.sbid != 0:
self.status.remove(self.sbSearchCId, self.sbid) self.status.remove(self.sbSearchCId, self.sbid)
@@ -669,6 +916,19 @@ class PyGTKtalog:
self.progress.set_fraction(0) self.progress.set_fraction(0)
#}}} #}}}
def __display_main_tree(self):
"""refresh tree with model form db"""
#{{{
try:
self.dirmodel = db.dbfile(self,self.con,self.cur).getDirectories()
except:
dialogs.Err("Error opening file - pyGTKtalog","Cannot open file %s." % self.opened_catalog)
self.newDB(self.window)
return
#self.dirmodel.set_sort_column_id(1,gtk.SORT_ASCENDING)
self.discs.set_model(self.dirmodel)
#}}}
def about(self,widget): def about(self,widget):
"""simple about dialog""" """simple about dialog"""
#{{{ #{{{