From baa5f3af6ea21894fe6a32c07ee8ab47a277ae59 Mon Sep 17 00:00:00 2001 From: gryf Date: Sat, 5 May 2007 20:17:53 +0000 Subject: [PATCH] * Old version of window, methods and stuff. --- mvc/old_main_window.py | 691 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 691 insertions(+) create mode 100644 mvc/old_main_window.py diff --git a/mvc/old_main_window.py b/mvc/old_main_window.py new file mode 100644 index 0000000..03c7b89 --- /dev/null +++ b/mvc/old_main_window.py @@ -0,0 +1,691 @@ +# This Python file uses the following encoding: utf-8 +""" +GUI, main window class and correspondig methods for pyGTKtalog app. +""" +#{{{ +licence = \ +""" +GPL v2 +http://www.gnu.org/licenses/gpl.txt +""" +#}}} + +__version__ = "0.5" +import sys +import os +import mimetypes +import popen2 +import datetime +import bz2 + +import pygtk +import gtk +import gtk.glade + +from pysqlite2 import dbapi2 as sqlite +import mx.DateTime + +from config import Config +import deviceHelper +import filetypeHelper +import dialogs +from preferences import Preferences +import db + +class PyGTKtalog: + def __init__(self): + """ init""" + # {{{ init + self.conf = Config() + self.conf.load() + + self.opened_catalog = None + self.db_tmp_filename = None + + self.progress = self.pygtkcat.get_widget("progressbar1") + + # trees + self.discs = self.pygtkcat.get_widget('discs') + c = gtk.TreeViewColumn('Filename') + cellpb = gtk.CellRendererPixbuf() + cell = gtk.CellRendererText() + c.pack_start(cellpb, False) + c.pack_start(cell, True) + c.set_attributes(cellpb, stock_id=2) + c.set_attributes(cell, text=1) + + self.discs.append_column(c) + + + self.files = self.pygtkcat.get_widget('files') + self.files.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + + c = gtk.TreeViewColumn('Filename') + cellpb = gtk.CellRendererPixbuf() + cell = gtk.CellRendererText() + c.pack_start(cellpb, False) + c.pack_start(cell, True) + c.set_attributes(cellpb, stock_id=6) + c.set_attributes(cell, text=1) + + c.set_sort_column_id(1) + c.set_resizable(True) + self.files.append_column(c) + + c = gtk.TreeViewColumn('Size',gtk.CellRendererText(), text=2) + c.set_sort_column_id(2) + c.set_resizable(True) + self.files.append_column(c) + + c = gtk.TreeViewColumn('Date',gtk.CellRendererText(), text=3) + c.set_sort_column_id(3) + c.set_resizable(True) + self.files.append_column(c) + + c = gtk.TreeViewColumn('Category',gtk.CellRendererText(), text=5) + c.set_sort_column_id(5) + c.set_resizable(True) + self.files.append_column(c) + + + # signals: + dic = {"on_main_destroy_event" :self.doQuit, + "on_quit1_activate" :self.doQuit, + "on_tb_quit_clicked" :self.doQuit, + "on_new1_activate" :self.newDB, + "on_tb_new_clicked" :self.newDB, + "on_add_cd_activate" :self.addCD, + "on_tb_addcd_clicked" :self.addCD, + "on_add_directory1_activate" :self.addDirectory, + "on_about1_activate" :self.about, + "on_properties1_activate" :self.preferences, + "on_status_bar1_activate" :self.toggle_status_bar, + "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" :self.show_files, + "on_discs_row_activated" :self.collapse_expand_branch, + "on_files_cursor_changed" :self.show_details, + "on_files_row_activated" :self.change_view, + } + + # connect signals + self.pygtkcat.signal_autoconnect(dic) + self.window.connect("delete_event", self.deleteEvent) + #}}} + + def collapse_expand_branch(self, treeview, path, treecolumn): + """if possible, expand or collapse branch of tree""" + #{{{ + if treeview.row_expanded(path): + treeview.collapse_row(path) + else: + treeview.expand_row(path,False) + #}}} + + def show_details(self,treeview): + """show details about file""" + #{{{ + model, paths = treeview.get_selection().get_selected_rows() + try: + itera = model.get_iter(paths[0]) + except: + if __debug__: + print "[mainwin.py] insufficient iterator" + return + + if model.get_value(itera,4) == 1: + #directory, do nothin', just turn off view + self.details.hide() + buf = self.details.get_buffer() + buf.set_text('') + self.details.set_buffer(buf) + if __debug__: + print "[mainwin.py] directory selected" + elif model.get_value(itera,4) > 1: + #file, show what you got. + self.details.show() + txt = db.dbfile(self,self.con,self.cur).getInfo(model.get_value(itera,0)) + buf = self.details.get_buffer() + buf.set_text(txt) + self.details.set_buffer(buf) + if __debug__: + print "[mainwin.py] some other thing selected" + #}}} + + def change_view(self, treeview, path, treecolumn): + """change directory deep down""" + #{{{ + model, paths = treeview.get_selection().get_selected_rows() + itera = model.get_iter(paths[0]) + current_id = model.get_value(itera,0) + if model.get_value(itera,4) == 1: + self.filemodel = db.dbfile(self,self.con,self.cur).getCurrentFiles(current_id) + self.files.set_model(self.filemodel) + + pat,col = self.discs.get_cursor() + if pat!=None: + if not self.discs.row_expanded(pat): + self.discs.expand_row(pat,False) + #self.discs.unselect_all() + + model, paths = self.discs.get_selection().get_selected_rows() + selected = None + new_iter = self.discs.get_model().iter_children(model.get_iter(pat)) + if new_iter: + while new_iter: + if model.get_value(new_iter,0) == current_id: + self.discs.set_cursor(model.get_path(new_iter)) + new_iter = model.iter_next(new_iter) + + + else: + #directory, do nothin', just turn off view + if __debug__: + print "[mainwin.py] directory selected" + #}}} + + def sort_files_view(self, model, iter1, iter2, data): + print 'aaaa' + + def show_files(self,treeview): + """show files after click on left side disc tree""" + #{{{ + model = treeview.get_model() + selected_item = model.get_value(model.get_iter(treeview.get_cursor()[0]),0) + self.filemodel = db.dbfile(self,self.con,self.cur).getCurrentFiles(selected_item) + self.files.set_model(self.filemodel) + + self.details.show() + txt = db.dbfile(self,self.con,self.cur).getInfo(selected_item) + buf = self.details.get_buffer() + buf.set_text(txt) + self.details.set_buffer(buf) + if __debug__: + print "[mainwin.py] some other thing selected" + + """ + iterator = treeview.get_model().get_iter_first(); + while iterator != None: + if model.get_value(iterator,0) == selected: + self.glade.get_widget(self.category_dict[model.get_value(iterator,0)]).show() + self.desc.set_markup("%s" % selected) + else: + self.glade.get_widget(self.category_dict[model.get_value(iterator,0)]).hide() + iterator = treeview.get_model().iter_next(iterator); + """ + #}}} + + 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.cur = self.con.cursor() + self.cur.execute("create table files(id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT, date datetime, 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): + """toggle visibility of toolbar bar""" + #{{{ + self.conf.confd['showtoolbar'] = self.menu_toolbar.get_active() + if self.menu_toolbar.get_active(): + self.toolbar.show() + else: + self.toolbar.hide() + #}}} + + def toggle_status_bar(self,widget): + """toggle visibility of statusbat and progress bar""" + #{{{ + self.conf.confd['showstatusbar'] = self.menu_statusbar.get_active() + if self.menu_statusbar.get_active(): + self.statusprogress.show() + else: + self.statusprogress.hide() + #}}} + + + + def preferences(self,widget): + """display preferences window""" + #{{{ + a = Preferences() + #}}} + + def doQuit(self, widget): + """quit and save window parameters to config file""" + #{{{ + try: + if widget.title: + pass + except: + # check if any unsaved project is on go. + try: + if self.unsaved_project: + if self.conf.confd['confirmquit']: + obj = dialogs.Qst('Quit application - pyGTKtalog','There is not saved database\nDo you really want to quit?') + if not obj.run(): + return + except AttributeError: + pass + self.storeSettings() + 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 + #}}} + + def newDB(self,widget): + """create database in temporary place""" + #{{{ + 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 + self.active_project = True + self.unsaved_project = False + + self.window.set_title("untitled - pyGTKtalog") + 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() + + # Create new database + 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) + + #clear treeview, if possible + try: + self.discs.get_model().clear() + except: + pass + try: + self.files.get_model().clear() + except: + pass + + #}}} + + def deleteEvent(self, widget, event, data=None): + """checkout actual database changed. If so, do the necessary ask.""" + #{{{ + try: + if self.unsaved_project: + if self.conf.confd['confirmquit']: + obj = dialogs.Qst('Quit application - pyGTKtalog','There is not saved database\nDo you really want to quit?') + if not obj.run(): + return True + except AttributeError: + pass + 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 + #}}} + + def run(self): + """show window and run app""" + #{{{ + self.window.show(); + gtk.main() + #}}} + + def addDirectory(self,widget): + """add directory structure from given location""" + #{{{ + obj = dialogs.PointDirectoryToAdd() + res = obj.run() + if res !=(None,None): + self.__scan(res[1],res[0]) + #}}} + + def addCD(self,widget): + """add directory structure from cd/dvd disc""" + #{{{ + mount = deviceHelper.volmount(self.conf.confd['cd']) + if mount == 'ok': + guessed_label = deviceHelper.volname(self.conf.confd['cd']) + obj = dialogs.InputDiskLabel(guessed_label) + label = obj.run() + if label != None: + + self.__scan(self.conf.confd['cd'],label) + + # umount/eject cd + if self.conf.confd['eject']: + msg = deviceHelper.eject_cd() + if msg != 'ok': + dialogs.Wrn("error ejecting device - pyGTKtalog","Cannot eject device pointed to %s.\nLast eject message:\n%s" % (self.conf.confd['cd'],msg)) + else: + msg = deviceHelper.volumount(self.conf.confd['cd']) + if msg != 'ok': + dialogs.Wrn("error unmounting device - pyGTKtalog","Cannot unmount device pointed to %s.\nLast umount message:\n%s" % (self.conf.confd['cd'],msg)) + else: + dialogs.Wrn("error mounting device - pyGTKtalog","Cannot mount device pointed to %s.\nLast mount message:\n%s" % (self.conf.confd['cd'],mount)) + #}}} + + def __scan(self,path,label,currentdb=None): + """scan content of the given path""" + #{{{ + mime = mimetypes.MimeTypes() + mov_ext = ('mkv','avi','ogg','mpg','wmv','mp4','mpeg') + img_ext = ('jpg','jpeg','png','gif','bmp','tga','tif','tiff','ilbm','iff','pcx') + + # count files in directory tree + count = 0 + if self.StatusbarID != 0: + self.status.remove(self.ContextID, self.StatusbarID) + self.StatusbarID = self.status.push(self.ContextID, "Calculating number of files in directory tree...") + for root,kat,plik in os.walk(path): + for p in plik: + count+=1 + while gtk.events_pending(): gtk.main_iteration() + frac = 1.0/count + + self.count = 0 + + def __recurse(path,name,wobj,date=0,frac=0,size=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 + """ + #{{{ + _size = size + walker = os.walk(path) + 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)) + + 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: + st = os.stat(os.path.join(root,i)) + _size = _size + __recurse(os.path.join(path,i),i,wobj,st.st_mtime,frac,0,currentid) + + for i in files: + self.count = self.count + 1 + st = os.stat(os.path.join(root,i)) + + ### scan files + if i[-3:].lower() in mov_ext or \ + mime.guess_type(i)!= (None,None) and \ + mime.guess_type(i)[0].split("/")[0] == 'video': + # video only + info = filetypeHelper.guess_video(os.path.join(root,i)) + elif i[-3:].lower() in img_ext or \ + mime.guess_type(i)!= (None,None) and \ + mime.guess_type(i)[0].split("/")[0] == 'image': + pass + ### end of scan + + # progress/status + if wobj.StatusbarID != 0: + wobj.status.remove(wobj.ContextID, wobj.StatusbarID) + wobj.StatusbarID = wobj.status.push(wobj.ContextID, "Scannig: %s" % (os.path.join(root,i))) + wobj.progress.set_fraction(frac * self.count) + # PyGTK FAQ entry 23.20 + while gtk.events_pending(): gtk.main_iteration() + + _size = _size + st.st_size + + 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'") + 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() + + self.cur.execute("update files set size=? where id=?",(_size, currentid)) + return _size + #}}} + + self.con.commit() + __recurse(path,label,self,0,frac) + self.unsaved_project = True + self.__display_main_tree() + + if self.StatusbarID != 0: + self.status.remove(self.ContextID, self.StatusbarID) + self.StatusbarID = self.status.push(self.ContextID, "Idle") + + 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): + """simple about dialog""" + #{{{ + dialogs.Abt("pyGTKtalog", __version__, "About", ["Roman 'gryf' Dobosz"], licence) + #}}} +