mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 11:30:19 +01:00
231 lines
7.4 KiB
Python
231 lines
7.4 KiB
Python
"""
|
|
Project: pyGTKtalog
|
|
Description: Model for main application
|
|
Type: core
|
|
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
|
|
Created: 2009-05-02
|
|
"""
|
|
import os
|
|
import bz2
|
|
from string import printable
|
|
from tempfile import mkstemp
|
|
|
|
import gtk
|
|
import gobject
|
|
from gtkmvc import ModelMT
|
|
|
|
from pygtktalog.dbobjects import File, Exif, Group, Gthumb
|
|
from pygtktalog.dbobjects import Image, Tag, Thumbnail
|
|
from pygtktalog.dbcommon import connect, Meta, Session
|
|
from pygtktalog.logger import get_logger
|
|
|
|
LOG = get_logger("main model")
|
|
|
|
|
|
class MainModel(ModelMT):
|
|
"""
|
|
Main model for application.
|
|
It is responsible for communicate with database objects and I/O
|
|
operations.
|
|
"""
|
|
status_bar_message = _("Idle")
|
|
current_disc = None
|
|
|
|
__observables__ = ("status_bar_message", "current_disc")
|
|
|
|
def __init__(self, filename=None):
|
|
"""
|
|
Initialization. Make some nice defaults.
|
|
Arguments:
|
|
filename - String that indicates optionally compressed with bzip2
|
|
file containing sqlite3 database.
|
|
"""
|
|
ModelMT.__init__(self)
|
|
# Opened/saved database location in filesystem. Could be compressed.
|
|
self.cat_fname = filename
|
|
# Temporary (usually in /tmp) working database.
|
|
self.tmp_filename = None
|
|
# Flag indicates, that db was compressed
|
|
# TODO: make it depend on configuration
|
|
self.compressed = False
|
|
|
|
self.db_unsaved = False
|
|
|
|
self.discs = gtk.TreeStore(gobject.TYPE_INT,
|
|
gobject.TYPE_STRING,
|
|
str,
|
|
gobject.TYPE_INT,
|
|
gobject.TYPE_PYOBJECT)
|
|
|
|
if self.cat_fname:
|
|
self.open(self.cat_fname)
|
|
|
|
def open(self, filename):
|
|
"""
|
|
Open catalog file and read db
|
|
Arguments:
|
|
@filename - see MainModel __init__ docstring.
|
|
Returns: Bool - true for success, false otherwise.
|
|
"""
|
|
LOG.debug("filename: '%s'", filename)
|
|
self.unsaved_project = False
|
|
if not os.path.exists(filename):
|
|
LOG.warn("db file '%s' doesn't exist.", filename)
|
|
return False
|
|
|
|
self.cat_fname = filename
|
|
|
|
if self._open_or_decompress():
|
|
return self._populate_discs_from_db()
|
|
else:
|
|
return False
|
|
|
|
def new(self):
|
|
"""
|
|
Create new catalog
|
|
"""
|
|
self._cleanup_and_create_temp_db_file()
|
|
|
|
def cleanup(self):
|
|
"""
|
|
Remove temporary directory tree from filesystem
|
|
"""
|
|
if self.tmp_filename is None:
|
|
return
|
|
|
|
try:
|
|
os.unlink(self.tmp_filename)
|
|
LOG.debug("file %s succesfully deleted", self.tmp_filename)
|
|
except OSError:
|
|
LOG.exception("temporary db file doesn't exists!")
|
|
except TypeError:
|
|
# TODO: file not exist - create? print error message?
|
|
LOG.exception("temporary db file doesn't exists!")
|
|
|
|
|
|
def _create_empty_db(self):
|
|
"""
|
|
Create new DB
|
|
"""
|
|
self._cleanup_and_create_temp_db_file()
|
|
|
|
def _examine_file(self, filename):
|
|
"""
|
|
Try to recognize file.
|
|
Arguments:
|
|
@filename - String with full path to file to examine
|
|
Returns: 'sql', 'bz2' or None for file sqlite, compressed with bzip2
|
|
or other respectively
|
|
"""
|
|
try:
|
|
head_of_file = open(filename).read(15)
|
|
LOG.debug("head of file: %s", filter(lambda x: x in printable,
|
|
head_of_file))
|
|
except IOError:
|
|
LOG.exception("Error opening file '%s'!", filename)
|
|
self.cleanup()
|
|
self.cat_fname = None
|
|
self.tmp_filename = None
|
|
return None
|
|
|
|
if head_of_file == "SQLite format 3":
|
|
LOG.debug("File format: uncompressed sqlite")
|
|
return 'sql'
|
|
elif head_of_file[0:10] == "BZh91AY&SY":
|
|
LOG.debug("File format: bzip2")
|
|
return 'bz2'
|
|
else:
|
|
return None
|
|
|
|
def _open_or_decompress(self):
|
|
"""
|
|
Try to open file, which user thinks is our catalog file.
|
|
Returns: Bool - true for success, false otherwise
|
|
"""
|
|
filename = os.path.abspath(self.cat_fname)
|
|
LOG.info("catalog file: %s", filename)
|
|
|
|
self._cleanup_and_create_temp_db_file()
|
|
LOG.debug("tmp database file: %s", str(self.tmp_filename))
|
|
|
|
examine = self._examine_file(filename)
|
|
if examine == "sql":
|
|
db_tmp = open(self.tmp_filename, "wb")
|
|
db_tmp.write(open(filename).read())
|
|
db_tmp.close()
|
|
elif examine == "bz2":
|
|
open_file = bz2.BZ2File(filename)
|
|
try:
|
|
db_tmp = open(self.tmp_filename, "w")
|
|
db_tmp.write(open_file.read())
|
|
db_tmp.close()
|
|
open_file.close()
|
|
except IOError:
|
|
self.cleanup()
|
|
self.filename = None
|
|
self.internal_dirname = None
|
|
LOG.exception("File is probably not a bz2!")
|
|
return False
|
|
if self._examine_file(self.tmp_filename) is not 'sql':
|
|
LOG.error("Error opening file '%s' - not a catalog file!",
|
|
self.tmp_filename)
|
|
self.cleanup()
|
|
self.cat_fname = None
|
|
self.tmp_filename = None
|
|
return False
|
|
|
|
else:
|
|
LOG.error("Error opening file '%s' - not a catalog file!",
|
|
self.tmp_filename)
|
|
self.cleanup()
|
|
self.filename = None
|
|
self.internal_dirname = None
|
|
return False
|
|
|
|
connect(os.path.abspath(self.tmp_filename))
|
|
return True
|
|
|
|
def _cleanup_and_create_temp_db_file(self):
|
|
self.cleanup()
|
|
fd, self.tmp_filename = mkstemp()
|
|
# close file descriptor, otherwise it can be source of app crash!
|
|
# http://www.logilab.org/blogentry/17873
|
|
os.close(fd)
|
|
|
|
def _populate_discs_from_db(self):
|
|
"""
|
|
Read objects from database, fill TreeStore model with discs
|
|
information
|
|
"""
|
|
session = Session()
|
|
dirs = session.query(File).filter(File.type == 1)
|
|
dirs = dirs.order_by(File.filename).all()
|
|
|
|
def get_children(parent_id=1, iterator=None):
|
|
"""
|
|
Get all children of the selected parent.
|
|
Arguments:
|
|
@parent_id - integer with id of the parent (from db)
|
|
@iterator - TODO
|
|
"""
|
|
for fileob in dirs:
|
|
if fileob.parent_id == parent_id:
|
|
myiter = self.discs.insert_before(iterator, None)
|
|
self.discs.set_value(myiter, 0, fileob.id)
|
|
self.discs.set_value(myiter, 1, fileob.filename)
|
|
if iterator is None:
|
|
self.discs.set_value(myiter, 2, gtk.STOCK_CDROM)
|
|
else:
|
|
self.discs.set_value(myiter, 2, gtk.STOCK_DIRECTORY)
|
|
self.discs.set_value(myiter, 3, fileob.parent_id)
|
|
self.discs.set_value(myiter, 4, fileob)
|
|
get_children(fileob.id, myiter)
|
|
return
|
|
get_children()
|
|
session.close()
|
|
|
|
return True
|
|
|
|
def get_root_entries(self, id):
|
|
LOG.debug("not implemented!, get_root_entries, id: %s", str(id))
|