mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 19:40:21 +01:00
Implementation of discs tree, added popup menu
This commit is contained in:
13
README
13
README
@@ -24,12 +24,15 @@ FEATURES
|
|||||||
REQUIREMENTS
|
REQUIREMENTS
|
||||||
------------
|
------------
|
||||||
|
|
||||||
pyGTKtalog is written in python with following dependencies:
|
pyGTKtalog was developed using python and following libraries:
|
||||||
|
|
||||||
* python 2.5 or higher (not tested on python 3000)
|
* python 2.6
|
||||||
* `pygtk 2.12 <http://www.pygtk.org>`_ or higher
|
* `pygtk 2.16 <http://www.pygtk.org>`_
|
||||||
* `pygtkmvc 1.99 <http://apps.sourceforge.net/trac/pygtkmvc/wiki>`_ or higher
|
* `pygtkmvc 1.99 <http://apps.sourceforge.net/trac/pygtkmvc/wiki>`_
|
||||||
* `sqlalchemy 0.5.5 <http://www.sqlalchemy.org>`_ or higher
|
* `sqlalchemy 0.6 <http://www.sqlalchemy.org>`_
|
||||||
|
|
||||||
|
It may work on other (lower) version of libraries, and it should work with
|
||||||
|
higher versions of libraries.
|
||||||
|
|
||||||
Optional modules
|
Optional modules
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Project: pyGTKtalog
|
Project: pyGTKtalog
|
||||||
Description: Initialize for main module - i18n and so.
|
Description: Initialization for main module - i18n and so.
|
||||||
Type: core
|
Type: core
|
||||||
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
|
Author: Roman 'gryf' Dobosz, gryf73@gmail.com
|
||||||
Created: 2009-05-05
|
Created: 2009-05-05
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from pygtktalog.logger import get_logger
|
|||||||
# setup SQLAlchemy logging facility
|
# setup SQLAlchemy logging facility
|
||||||
# TODO: Logger("sqlalchemy")
|
# TODO: Logger("sqlalchemy")
|
||||||
# or maybe it will be better to separate sqlalchemy stuff from application
|
# or maybe it will be better to separate sqlalchemy stuff from application
|
||||||
get_logger("sqlalchemy", 'INFO')
|
#get_logger("sqlalchemy", 'INFO')
|
||||||
|
|
||||||
# Prepare SQLAlchemy objects
|
# Prepare SQLAlchemy objects
|
||||||
Meta = MetaData()
|
Meta = MetaData()
|
||||||
|
|||||||
@@ -40,10 +40,13 @@ def get_logger(module_name, level=None, to_file=False):
|
|||||||
|
|
||||||
if to_file:
|
if to_file:
|
||||||
log_handler = logging.FileHandler(path)
|
log_handler = logging.FileHandler(path)
|
||||||
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno) - %(name)s - %(levelname)s - %(message)s")
|
formatter = logging.Formatter("%(asctime)s %(filename)s:%(lineno) - "
|
||||||
|
"%(name)s - %(levelname)s - "
|
||||||
|
"%(message)s")
|
||||||
else:
|
else:
|
||||||
log_handler = logging.StreamHandler(sys.stderr)
|
log_handler = logging.StreamHandler(sys.stderr)
|
||||||
formatter = logging.Formatter("%(name)s - %(filename)s:%(lineno)s - %(levelname)s - %(message)s")
|
formatter = logging.Formatter("%(name)s - %(filename)s:%(lineno)s - "
|
||||||
|
"%(levelname)s - %(message)s")
|
||||||
|
|
||||||
log_handler.setFormatter(formatter)
|
log_handler.setFormatter(formatter)
|
||||||
log.addHandler(log_handler)
|
log.addHandler(log_handler)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import bz2
|
import bz2
|
||||||
|
from string import printable
|
||||||
from tempfile import mkstemp
|
from tempfile import mkstemp
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
@@ -22,17 +23,26 @@ LOG = get_logger("main model")
|
|||||||
|
|
||||||
|
|
||||||
class MainModel(ModelMT):
|
class MainModel(ModelMT):
|
||||||
|
"""
|
||||||
|
Main model for application.
|
||||||
|
It is responsible for communicate with database objects and I/O
|
||||||
|
operations.
|
||||||
|
"""
|
||||||
status_bar_message = _("Idle")
|
status_bar_message = _("Idle")
|
||||||
current_disc = None
|
current_disc = None
|
||||||
|
|
||||||
__observables__ = ("status_bar_message", "current_disc")
|
__observables__ = ("status_bar_message", "current_disc")
|
||||||
|
|
||||||
def __init__(self, filename=None):
|
def __init__(self, filename=None):
|
||||||
"""Initialization. Make some nice defaults."""
|
"""
|
||||||
print "model"
|
Initialization. Make some nice defaults.
|
||||||
|
Arguments:
|
||||||
|
filename - String that indicates optionally compressed with bzip2
|
||||||
|
file containing sqlite3 database.
|
||||||
|
"""
|
||||||
ModelMT.__init__(self)
|
ModelMT.__init__(self)
|
||||||
# Opened/saved database location in filesystem. Could be compressed.
|
# Opened/saved database location in filesystem. Could be compressed.
|
||||||
self.db_filename = filename
|
self.cat_fname = filename
|
||||||
# Temporary (usually in /tmp) working database.
|
# Temporary (usually in /tmp) working database.
|
||||||
self.tmp_filename = None
|
self.tmp_filename = None
|
||||||
# Flag indicates, that db was compressed
|
# Flag indicates, that db was compressed
|
||||||
@@ -41,45 +51,50 @@ class MainModel(ModelMT):
|
|||||||
|
|
||||||
self.db_unsaved = False
|
self.db_unsaved = False
|
||||||
|
|
||||||
self.discs = gtk.TreeStore(str, gobject.TYPE_STRING)
|
self.discs = gtk.TreeStore(gobject.TYPE_INT,
|
||||||
|
gobject.TYPE_STRING,
|
||||||
|
str,
|
||||||
|
gobject.TYPE_INT)
|
||||||
|
|
||||||
# XXX remove this on production!
|
if self.cat_fname:
|
||||||
myiter = self.discs.insert_before(None, None)
|
self.open(self.cat_fname)
|
||||||
self.discs.set_value(myiter, 1, "bubu")
|
|
||||||
self.discs.set_value(myiter, 1, "foo")
|
|
||||||
self.discs.set_value(myiter, 1, "bar")
|
|
||||||
|
|
||||||
itr = self.discs.append(None, None)
|
def open(self, filename):
|
||||||
self.discs.set_value(itr, 0, gtk.STOCK_DIRECTORY)
|
"""
|
||||||
self.discs.set_value(itr, 1, "foobar")
|
Open catalog file and read db
|
||||||
for nr, name in enumerate(('foo', 'bar', 'baz')):
|
Arguments:
|
||||||
self.discs.append(itr, (gtk.STOCK_FILE, "%s %d" % (name, nr)))
|
@filename - see MainModel __init__ docstring.
|
||||||
|
Returns: Bool - true for success, false otherwise.
|
||||||
#self.open()
|
"""
|
||||||
|
LOG.debug("filename: '%s'", filename)
|
||||||
def open(self, filename=None):
|
|
||||||
self.unsaved_project = False
|
self.unsaved_project = False
|
||||||
if filename is not None and not os.path.exists(filename):
|
if not os.path.exists(filename):
|
||||||
LOG.warn("db file '%s' doesn't exist", filename)
|
LOG.warn("db file '%s' doesn't exist.", filename)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if filename:
|
self.cat_fname = filename
|
||||||
self.db_filename = filename
|
|
||||||
if self.db_filename:
|
if self._open_or_decompress():
|
||||||
return self.__open_or_decompress()
|
return self._read_db()
|
||||||
else:
|
else:
|
||||||
self.__create_empty_db()
|
return False
|
||||||
return True
|
|
||||||
|
def new(self):
|
||||||
|
"""
|
||||||
|
Create new catalog
|
||||||
|
"""
|
||||||
|
self._cleanup_and_create_temp_db_file()
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
"""remove temporary directory tree from filesystem"""
|
"""
|
||||||
|
Remove temporary directory tree from filesystem
|
||||||
|
"""
|
||||||
if self.tmp_filename is None:
|
if self.tmp_filename is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
#import ipdb; ipdb.set_trace()
|
|
||||||
LOG.debug("cleanup()")
|
|
||||||
try:
|
try:
|
||||||
os.unlink(self.tmp_filename)
|
os.unlink(self.tmp_filename)
|
||||||
|
LOG.debug("file %s succesfully deleted", self.tmp_filename)
|
||||||
except OSError:
|
except OSError:
|
||||||
LOG.exception("temporary db file doesn't exists!")
|
LOG.exception("temporary db file doesn't exists!")
|
||||||
except TypeError:
|
except TypeError:
|
||||||
@@ -87,32 +102,57 @@ class MainModel(ModelMT):
|
|||||||
LOG.exception("temporary db file doesn't exists!")
|
LOG.exception("temporary db file doesn't exists!")
|
||||||
|
|
||||||
|
|
||||||
def __create_empty_db(self):
|
def _create_empty_db(self):
|
||||||
pass
|
"""
|
||||||
|
Create new DB
|
||||||
|
"""
|
||||||
|
self._cleanup_and_create_temp_db_file()
|
||||||
|
|
||||||
def __open_or_decompress(self):
|
def _examine_file(self, filename):
|
||||||
filename = os.path.abspath(self.db_filename)
|
"""
|
||||||
LOG.info("database file: %s", 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
|
||||||
|
|
||||||
self.__cleanup_and_create_temp_db_file()
|
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))
|
LOG.debug("tmp database file: %s", str(self.tmp_filename))
|
||||||
|
|
||||||
try:
|
examine = self._examine_file(filename)
|
||||||
test_file = open(filename).read(15)
|
if examine == "sql":
|
||||||
LOG.debug("test_file: %s", test_file)
|
|
||||||
except IOError:
|
|
||||||
self.cleanup()
|
|
||||||
self.db_filename = None
|
|
||||||
self.tmp_filename = None
|
|
||||||
LOG.exception("Error opening file!")
|
|
||||||
return False
|
|
||||||
|
|
||||||
if test_file == "SQLite format 3":
|
|
||||||
db_tmp = open(self.tmp_filename, "wb")
|
db_tmp = open(self.tmp_filename, "wb")
|
||||||
db_tmp.write(open(filename).read())
|
db_tmp.write(open(filename).read())
|
||||||
db_tmp.close()
|
db_tmp.close()
|
||||||
LOG.debug("file format: sqlite")
|
elif examine == "bz2":
|
||||||
elif test_file[0:10] == "BZh91AY&SY":
|
|
||||||
open_file = bz2.BZ2File(filename)
|
open_file = bz2.BZ2File(filename)
|
||||||
try:
|
try:
|
||||||
db_tmp = open(self.tmp_filename, "w")
|
db_tmp = open(self.tmp_filename, "w")
|
||||||
@@ -120,27 +160,67 @@ class MainModel(ModelMT):
|
|||||||
db_tmp.close()
|
db_tmp.close()
|
||||||
open_file.close()
|
open_file.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
# file is not bz2
|
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.filename = None
|
self.filename = None
|
||||||
self.internal_dirname = None
|
self.internal_dirname = None
|
||||||
# TODO: add logger
|
|
||||||
LOG.exception("File is probably not a bz2!")
|
LOG.exception("File is probably not a bz2!")
|
||||||
return False
|
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:
|
else:
|
||||||
|
LOG.error("Error opening file '%s' - not a catalog file!",
|
||||||
|
self.tmp_filename)
|
||||||
|
self.cleanup()
|
||||||
self.filename = None
|
self.filename = None
|
||||||
self.internal_dirname = None
|
self.internal_dirname = None
|
||||||
return False
|
return False
|
||||||
|
|
||||||
connect(os.path.abspath(self.tmp_filename))
|
connect(os.path.abspath(self.tmp_filename))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __cleanup_and_create_temp_db_file(self):
|
def _cleanup_and_create_temp_db_file(self):
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
fd, self.tmp_filename = mkstemp()
|
fd, self.tmp_filename = mkstemp()
|
||||||
# close file descriptor, otherwise it can be source of app crash!
|
# close file descriptor, otherwise it can be source of app crash!
|
||||||
# http://www.logilab.org/blogentry/17873
|
# http://www.logilab.org/blogentry/17873
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
|
|
||||||
|
def _read_db(self):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
session = Session()
|
||||||
|
dirs = session.query(File).filter(File.type == 1).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)
|
||||||
|
get_children(fileob.id, myiter)
|
||||||
|
return
|
||||||
|
get_children()
|
||||||
|
session.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
# TODO: get this thing right
|
# TODO: get this thing right
|
||||||
def get_root_entries(self, id):
|
def get_root_entries(self, id):
|
||||||
LOG.debug("id: %s" (type(id)))
|
LOG.debug("id: %s", str(id))
|
||||||
|
|||||||
@@ -53,21 +53,21 @@ class DiscsView(View):
|
|||||||
Initialize view
|
Initialize view
|
||||||
"""
|
"""
|
||||||
View.__init__(self)
|
View.__init__(self)
|
||||||
#self.discs_popup = DiscsPopupView()
|
self.popup_menu = DiscsPopupView()
|
||||||
|
|
||||||
|
|
||||||
#class DiscsPopupView(View):
|
class DiscsPopupView(View):
|
||||||
# """
|
"""
|
||||||
# Separate Discs PopUp subview.
|
Separate Discs PopUp subview.
|
||||||
# """
|
"""
|
||||||
# glade = get_glade("discs.glade")
|
glade = get_glade("discs.glade")
|
||||||
# top = 'discs_popup'
|
top = 'discs_popup'
|
||||||
|
|
||||||
# def __init__(self):
|
def __init__(self):
|
||||||
# """
|
"""
|
||||||
# Initialize view
|
Initialize view
|
||||||
# """
|
"""
|
||||||
# View.__init__(self)
|
View.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
#class FilesView(View):
|
#class FilesView(View):
|
||||||
|
|||||||
Reference in New Issue
Block a user