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

1069 lines
41 KiB
Python

# This Python file uses the following encoding: utf-8
#
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
#
# Copyright (C) 2007 by Roman 'gryf' Dobosz
#
# This file is part of pyGTKtalog.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# -------------------------------------------------------------------------
import os
import sys
import base64
import shutil
import tarfile
import tempfile
import string
import gtk
import gobject
from gtkmvc.model_mt import ModelMT
from pysqlite2 import dbapi2 as sqlite
from datetime import datetime
try:
import threading as _threading
except ImportError:
import dummy_threading as _threading
from m_config import ConfigModel
from m_details import DetailsModel
from utils.thumbnail import Thumbnail
from utils.img import Img
from utils.parse_exif import ParseExif
class MainModel(ModelMT):
"""Create, load, save, manipulate db file which is container for data"""
__properties__ = {'busy': False, 'statusmsg': '', 'progress': 0}
# constants instead of dictionary tables
# type of files
LAB = 0 # root of the tree - label/collection name
DIR = 1 # directory
FIL = 2 # file
LIN = 3 # symbolic link
CD = 1 # sorce: cd/dvd
DR = 2 # source: filesystem
EXIF_DICT= {0: 'Camera',
1: 'Date',
2: 'Aperture',
3: 'Exposure program',
4: 'Exposure bias',
5: 'ISO',
6: 'Focal length',
7: 'Subject distance',
8: 'Metering mode',
9: 'Flash',
10: 'Light source',
11: 'Resolution',
12: 'Orientation'}
# images extensions - only for PIL and EXIF
IMG = ['jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff', 'tga', 'pcx', 'bmp',
'xbm', 'xpm', 'jp2', 'jpx', 'pnm']
def __init__(self):
ModelMT.__init__(self)
self.config = ConfigModel()
self.unsaved_project = False
self.filename = None # catalog saved/opened filename
self.internal_dirname = None
self.db_connection = None
self.db_cursor = None
self.abort = False
self.source = self.CD
self.config.load()
self.details = DetailsModel()
# Directory tree: id, name, icon, type
self.discs_tree = gtk.TreeStore(gobject.TYPE_INT, gobject.TYPE_STRING,
str, gobject.TYPE_INT)
# File list of selected directory: child_id(?), filename, size,
# date, type, icon
self.files_list = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING,
gobject.TYPE_UINT64,
gobject.TYPE_STRING, gobject.TYPE_INT,
gobject.TYPE_STRING, str)
# iconview store - id, pixbuffer
self.images_store = gtk.ListStore(gobject.TYPE_INT, gtk.gdk.Pixbuf)
# exif liststore - id, exif key, exif value
self.exif_list = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING,
gobject.TYPE_STRING)
# tag cloud array element is a dict with 4 keys:
# elem = {'id': str(id), 'name': tagname, 'size': size, 'color': color}
# where color is in one of format:
# - named (i.e. red, blue, black and so on)
# - #rgb
# - #rrggbb
self.tag_cloud = []
'''{'id': str(1), 'name': "bezpieczeństwo", 'size': 10, 'color': '#666'},
{'id': str(2), 'name': "bsd", 'size': 14, 'color': '#333'},
{'id': str(3), 'name': "debian", 'size': 18, 'color': '#333'},
{'id': str(4), 'name': "fedora", 'size': 12, 'color': '#666'},
{'id': str(5), 'name': "firefox", 'size': 40, 'color': '#666'},
{'id': str(6), 'name': "gnome", 'size': 26, 'color': '#333'},
{'id': str(7), 'name': "gentoo", 'size': 30, 'color': '#000'},
{'id': str(8), 'name': "kde", 'size': 20, 'color': '#333'},
{'id': str(9), 'name': "kernel", 'size': 10, 'color': '#666'},
{'id': str(10), 'name': "windows", 'size': 18, 'color': '#333'},
]'''
return
def add_image(self, image, id):
sql = """insert into images(file_id, thumbnail, filename)
values(?, null, null)"""
self.db_cursor.execute(sql, (id,))
self.db_connection.commit()
sql = """select id from images where thumbnail is null and filename is null and file_id=?"""
self.db_cursor.execute(sql, (id,))
res = self.db_cursor.fetchone()
if res:
tp, ip, rc = Img(image, self.internal_dirname).save(res[0])
if rc != -1:
sql = """update images set filename=?, thumbnail=? where id=?"""
self.db_cursor.execute(sql,
(ip.split(self.internal_dirname)[1][1:],
tp.split(self.internal_dirname)[1][1:],
res[0]))
self.db_connection.commit()
def cleanup(self):
self.__close_db_connection()
if self.internal_dirname != None:
try:
shutil.rmtree(self.internal_dirname)
except:
pass
return
def new(self):
self.unsaved_project = False
self.__create_internal_dirname()
self.__connect_to_db()
self.__create_database()
self.__clear_trees()
return
def save(self, filename=None):
"""save tared directory at given catalog fielname"""
if not filename and not self.filename:
if __debug__:
return False, "no filename detected!"
return
if filename:
self.filename = filename
val, err = self.__compress_and_save()
if not val:
self.filename = None
return val, err
def open(self, filename=None):
"""try to open db file"""
self.unsaved_project = False
self.__create_internal_dirname()
self.filename = filename
try:
tar = tarfile.open(filename, "r:gz")
except:
try:
tar = tarfile.open(filename, "r")
except:
self.filename = None
self.internal_dirname = None
return
os.chdir(self.internal_dirname)
try:
tar.extractall()
print "m_main.py: extracted tarfile into", self.internal_dirname
except AttributeError:
# python's 2.4 tarfile module lacks of method extractall()
directories = []
for tarinfo in tar:
if tarinfo.isdir():
# Extract directory with a safe mode, so that
# all files below can be extracted as well.
try:
os.makedirs(os.path.join(path, tarinfo.name), 0777)
except EnvironmentError:
pass
directories.append(tarinfo)
else:
tar.extract(tarinfo, '.')
# Reverse sort directories.
directories.sort(lambda a, b: cmp(a.name, b.name))
directories.reverse()
# Set correct owner, mtime and filemode on directories.
for tarinfo in directories:
path = os.path.join(path, tarinfo.name)
try:
os.chown(tarinfo, '.')
os.utime(tarinfo, '.')
os.chmod(tarinfo, '.')
except ExtractError, e:
if tar.errorlevel > 1:
raise
else:
tar._dbg(1, "tarfile: %s" % e)
tar.close()
self.__connect_to_db()
self.__fetch_db_into_treestore()
self.config.add_recent(filename)
return True
def scan(self, path, label, currentid):
"""scan files in separated thread"""
# flush buffer to release db lock.
self.db_connection.commit()
self.path = path
self.label = label
self.currentid = currentid
if self.busy:
return
self.thread = _threading.Thread(target=self.__scan)
self.thread.start()
return
def rename(self, id, new_name=None):
if new_name:
self.db_cursor.execute("update files set filename=? \
where id=?", (new_name, id))
self.db_connection.commit()
self.__fetch_db_into_treestore()
self.unsaved_project = True
else:
if __debug__:
print "m_main.py: rename(): no label defined"
return
def refresh_discs_tree(self):
self.__fetch_db_into_treestore()
def get_root_entries(self, id=None):
"""Get all children down from sepcified root"""
try:
self.files_list.clear()
except:
pass
# directories first
self.db_cursor.execute("SELECT id, filename, size, date FROM files \
WHERE parent_id=? AND type=1 \
ORDER BY filename", (id,))
data = self.db_cursor.fetchall()
for ch in data:
myiter = self.files_list.insert_before(None, None)
self.files_list.set_value(myiter, 0, ch[0])
self.files_list.set_value(myiter, 1, ch[1])
self.files_list.set_value(myiter, 2, ch[2])
self.files_list.set_value(myiter, 3,
datetime.fromtimestamp(ch[3]))
self.files_list.set_value(myiter, 4, 1)
self.files_list.set_value(myiter, 5, 'direktorja')
self.files_list.set_value(myiter, 6, gtk.STOCK_DIRECTORY)
# all the rest
self.db_cursor.execute("SELECT f.id, f.filename, f.size, f.date, \
f.type FROM files f \
WHERE f.parent_id=? AND f.type!=1 \
ORDER BY f.filename", (id,))
data = self.db_cursor.fetchall()
for ch in data:
myiter = self.files_list.insert_before(None, None)
self.files_list.set_value(myiter, 0, ch[0])
self.files_list.set_value(myiter, 1, ch[1])
self.files_list.set_value(myiter, 2, ch[2])
self.files_list.set_value(myiter, 3, datetime.fromtimestamp(ch[3]))
self.files_list.set_value(myiter, 4, ch[4])
self.files_list.set_value(myiter, 5, 'kategoria srategoria')
if ch[4] == self.FIL:
self.files_list.set_value(myiter, 6, gtk.STOCK_FILE)
elif ch[4] == self.LIN:
self.files_list.set_value(myiter, 6, gtk.STOCK_INDEX)
return
def get_parent_discs_value(self, child_id):
if child_id:
self.db_cursor.execute("SELECT parent_id FROM files where id=?", (child_id,))
set = self.db_cursor.fetchone()
if set:
return set[0]
return None
def get_file_info(self, id):
"""get file info from database"""
retval = {}
sql = """SELECT f.filename, f.date, f.size, f.type,
t.filename, f.description
FROM files f
LEFT JOIN thumbnails t ON t.file_id = f.id
WHERE f.id = ?"""
self.db_cursor.execute(sql, (id,))
set = self.db_cursor.fetchone()
if set:
string = "ID: %d\nFilename: %s\nDate: %s\nSize: %s\ntype: %s" % \
(id, set[0], datetime.fromtimestamp(set[1]), set[2], set[3])
retval['file_info'] = string
if set[5]:
retval['description'] = set[5]
if set[4]:
retval['thumbnail'] = os.path.join(self.internal_dirname, set[4])
sql = """SELECT id, filename, thumbnail from images WHERE file_id = ?"""
self.db_cursor.execute(sql, (id,))
set = self.db_cursor.fetchall()
if set:
self.images_store = gtk.ListStore(gobject.TYPE_INT, gtk.gdk.Pixbuf)
for id, img, thb in set:
im = os.path.join(self.internal_dirname,thb)
pix = gtk.gdk.pixbuf_new_from_file(im)
self.images_store.append([id, pix])
retval['images'] = True
sql = """SELECT camera, date, aperture, exposure_program,
exposure_bias, iso, focal_length, subject_distance, metering_mode,
flash, light_source, resolution, orientation
from exif
WHERE file_id = ?"""
self.db_cursor.execute(sql, (id,))
set = self.db_cursor.fetchone()
if set:
self.exif_list = gtk.ListStore(gobject.TYPE_STRING,
gobject.TYPE_STRING)
for key in self.EXIF_DICT:
myiter = self.exif_list.insert_before(None, None)
self.exif_list.set_value(myiter, 0, self.EXIF_DICT[key])
self.exif_list.set_value(myiter, 1, set[key])
retval['exif'] = True
return retval
def get_source(self, path):
"""get source of top level directory"""
bid = self.discs_tree.get_value(self.discs_tree.get_iter(path[0]),
0)
self.db_cursor.execute("select source from files where id = ?",
(bid,))
res = self.db_cursor.fetchone()
if res == None:
return False
return int(res[0])
def get_label_and_filepath(self, path):
"""get source of top level directory"""
bid = self.discs_tree.get_value(self.discs_tree.get_iter(path),
0)
self.db_cursor.execute("select filepath, filename from files \
where id = ? and parent_id = 1", (bid,))
res = self.db_cursor.fetchone()
if res == None:
return None, None
return res[0], res[1]
def delete_image(self, id):
"""removes image on specified id"""
sql = """select filename, thumbnail from images where id=?"""
self.db_cursor.execute(sql, (id,))
res = self.db_cursor.fetchone()
if res[0]:
os.unlink(os.path.join(self.internal_dirname, res[0]))
os.unlink(os.path.join(self.internal_dirname, res[1]))
if __debug__:
print "m_main.py: delete_image(): removed images:"
print res[0]
print res[1]
# remove images records
sql = """delete from images where id = ?"""
self.db_cursor.execute(sql, (id,))
self.db_connection.commit()
def delete(self, root_id, db_cursor=None, db_connection=None):
"""Remove subtree from main tree, remove tags from database
remove all possible data, like thumbnails"""
# TODO: opanowac syf zwiazany z tym, ze katalogi teraz przechowuja dane nieprawdziwe
fids = []
if not db_cursor:
db_cursor = self.db_cursor
if not db_connection:
db_connection = self.db_connection
def get_children(fid):
fids.append(fid)
sql = """select id from files where parent_id = ?"""
db_cursor.execute(sql, (fid,))
res = db_cursor.fetchall()
if len(res)>0:
for i in res:
get_children(i[0])
get_children(root_id)
def generator():
for c in fids:
yield (c,)
# remove files records
sql = """delete from files where id = ?"""
db_cursor.executemany(sql, generator())
# remove tags records
sql = """delete from tags_files where file_id = ?"""
db_cursor.executemany(sql, generator())
# remove thumbnails
arg =''
for c in fids:
if len(arg) > 0:
arg+=", %d" % c
else:
arg = "%d" % c
sql = """select filename from thumbnails where file_id in (%s)""" % arg
db_cursor.execute(sql)
res = db_cursor.fetchall()
if len(res) > 0:
for fn in res:
os.unlink(os.path.join(self.internal_dirname, fn[0]))
# remove images
sql = """select filename, thumbnail from images where file_id in (%s)""" % arg
db_cursor.execute(sql)
res = db_cursor.fetchall()
if res[0][0]:
for fn in res:
os.unlink(os.path.join(self.internal_dirname, fn[0]))
# remove thumbs records
sql = """delete from thumbnails where file_id = ?"""
db_cursor.executemany(sql, generator())
# remove images records
sql = """delete from images where file_id = ?"""
db_cursor.executemany(sql, generator())
db_connection.commit()
return
def get_stats(self, selected_id):
"""get statistic information"""
retval = {}
if selected_id:
sql = """select id, type, parent_id from files where id=?"""
self.db_cursor.execute(sql, (selected_id,))
res = self.db_cursor.fetchone()
if not res:
return retval
selected_item = {'id':res[0], 'type':res[1], 'parent': res[2]}
# collect all parent_id's
parents = []
def _recurse(fid):
parents.append(fid)
sql = """select id from files where type=? and parent_id=? and parent_id!=1"""
self.db_cursor.execute(sql, (self.DIR, fid))
res = self.db_cursor.fetchall()
if res:
for row in res:
_recurse(row[0])
_recurse(selected_id)
if selected_item['parent'] == 1:
parents.pop(0)
retval['discs'] = 1
retval['dirs'] = len(parents)
parents.append(selected_id)
files_count = 0
for p in parents:
sql = """select count(id) from files where type!=0 and type!=1 and parent_id=?"""
self.db_cursor.execute(sql, (p,))
res = self.db_cursor.fetchone()
if res:
files_count+=res[0]
retval['files'] = files_count
sql = """select size from files where id=?"""
self.db_cursor.execute(sql, (selected_id,))
res = self.db_cursor.fetchone()
if res:
retval['size'] = self.__bytes_to_human(res[0])
else:
sql = """select count(id) from files where parent_id=1 and type=1"""
self.db_cursor.execute(sql)
res = self.db_cursor.fetchone()
if res:
retval['discs'] = res[0]
sql = """select count(id) from files where parent_id!=1 and type=1"""
self.db_cursor.execute(sql)
res = self.db_cursor.fetchone()
if res:
retval['dirs'] = res[0]
sql = """select count(id) from files where parent_id!=1 and type!=1"""
self.db_cursor.execute(sql)
res = self.db_cursor.fetchone()
if res:
retval['files'] = res[0]
sql = """select sum(size) from files where parent_id=1 and type=1"""
self.db_cursor.execute(sql)
res = self.db_cursor.fetchone()
if res:
retval['size'] = self.__bytes_to_human(res[0])
return retval
def get_image_path(self, img_id):
"""return image location"""
sql = """select filename from images where id=?"""
self.db_cursor.execute(sql, (img_id,))
res = self.db_cursor.fetchone()
if res:
return res[0]
return None
# private class functions
def __bytes_to_human(self, integer):
if integer <= 0 or integer < 1024:
return "%d bytes" % integer
## convert integer into string with thousands' separator
#for i in range(len(str(integer))/3+1):
# if i == 0:
# s_int = str(integer)[-3:]
# else:
# s_int = str(integer)[-(3*int(i)+3):-(3*int(i))] + " " + s_int
t = integer
for power in ['kB', 'MB', 'GB', 'TB']:
t = t /1024.0
if t < 1 or t < 1024:
break
return "%0.2f %s (%d bytes)" % (t, power, integer)
def __clear_trees(self):
self.__clear_files_tree()
self.__clear_discs_tree()
def __clear_discs_tree(self):
try:
self.discs_tree.clear()
except:
pass
def __clear_files_tree(self):
try:
self.files_list.clear()
except:
pass
def __connect_to_db(self):
self.db_connection = sqlite.connect("%s" % \
(self.internal_dirname + '/db.sqlite'),
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
self.db_cursor = self.db_connection.cursor()
return
def __close_db_connection(self):
if self.db_cursor != None:
self.db_cursor.close()
self.db_cursor = None
if self.db_connection != None:
self.db_connection.close()
self.db_connection = None
return
def __create_internal_dirname(self):
self.cleanup()
self.internal_dirname = "/tmp/pygtktalog%d" % datetime.now().microsecond
try:
os.mkdir(self.internal_dirname)
except IOError, (errno, strerror):
print "m_main.py: __create_internal_dirname(): ", strerror
return
def __compress_and_save(self):
try:
if self.config.confd['compress']:
tar = tarfile.open(self.filename, "w:gz")
else:
tar = tarfile.open(self.filename, "w")
if __debug__:
print "m_main.py: __compress_and_save(): tar open successed"
except IOError, (errno, strerror):
return False, strerror
os.chdir(self.internal_dirname)
tar.add('.')
tar.close()
self.unsaved_project = False
return True, None
def __create_database(self):
"""make all necessary tables in db file"""
self.db_cursor.execute("""create table
files(id INTEGER PRIMARY KEY AUTOINCREMENT,
parent_id INTEGER,
filename TEXT,
filepath TEXT,
date datetime,
size INTEGER,
type INTEGER,
source INTEGER,
note TEXT,
description TEXT);""")
self.db_cursor.execute("""create table
tags(id INTEGER PRIMARY KEY AUTOINCREMENT,
group_id INTEGER,
tag TEXT);""")
self.db_cursor.execute("""create table
tags_files(file_id INTEGER,
tag_id INTEGER);""")
self.db_cursor.execute("""create table
groups(id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
color TEXT);""")
self.db_cursor.execute("""create table
thumbnails(id INTEGER PRIMARY KEY AUTOINCREMENT,
file_id INTEGER,
filename TEXT);""")
self.db_cursor.execute("""create table
images(id INTEGER PRIMARY KEY AUTOINCREMENT,
file_id INTEGER,
thumbnail TEXT,
filename TEXT);""")
self.db_cursor.execute("""create table
exif(id INTEGER PRIMARY KEY AUTOINCREMENT,
file_id INTEGER,
camera TEXT,
date TEXT,
aperture TEXT,
exposure_program TEXT,
exposure_bias TEXT,
iso TEXT,
focal_length TEXT,
subject_distance TEXT,
metering_mode TEXT,
flash TEXT,
light_source TEXT,
resolution TEXT,
orientation TEXT);""")
self.db_cursor.execute("insert into files values(1, 1, 'root', null, 0, 0, 0, 0, null, null);")
self.db_cursor.execute("insert into groups values(1, 'default', 'black');")
def __scan(self):
"""scan content of the given path"""
self.busy = True
# new conection for this task, because it's running in separate thread
db_connection = sqlite.connect("%s" % \
(self.internal_dirname + '/db.sqlite'),
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES,
isolation_level="EXCLUSIVE")
db_cursor = db_connection.cursor()
timestamp = datetime.now()
# count files in directory tree
count = 0
self.statusmsg = "Calculating number of files in directory tree..."
count = 0
try:
for root, dirs, files in os.walk(self.path):
count += len(files)
except:
if __debug__:
print 'm_main.py: os.walk in %s' % self.path
pass
if count > 0:
step = 1.0/count
else:
step = 1.0
self.count = 0
# guess filesystem encoding
self.fsenc = sys.getfilesystemencoding()
self.fresh_disk_iter = None
def __recurse(parent_id, name, path, date, size, filetype,
discs_tree_iter=None):
"""recursive scans given path"""
if self.abort:
return -1
_size = size
myit = self.discs_tree.append(discs_tree_iter, None)
if parent_id == 1:
self.fresh_disk_iter = myit
self.discs_tree.set_value(myit,2,gtk.STOCK_CDROM)
sql = """insert into
files(parent_id, filename, filepath, date, size, type, source)
values(?,?,?,?,?,?,?)"""
db_cursor.execute(sql, (parent_id, name, path, date, size,
filetype, self.source))
else:
self.discs_tree.set_value(myit,2,gtk.STOCK_DIRECTORY)
sql = """
insert into
files(parent_id, filename, filepath, date, size, type)
values(?,?,?,?,?,?)
"""
db_cursor.execute(sql,
(parent_id, name, path, date, size, filetype))
sql = """select seq FROM sqlite_sequence WHERE name='files'"""
db_cursor.execute(sql)
currentid=db_cursor.fetchone()[0]
self.discs_tree.set_value(myit,0,currentid)
self.discs_tree.set_value(myit,1,name)
self.discs_tree.set_value(myit,3,parent_id)
try:
root, dirs, files = os.walk(path).next()
except:
if __debug__:
print "m_main.py: cannot access ", path
#return -1
return 0
#############
# directories
for i in dirs:
j = self.__decode_filename(i)
current_dir = os.path.join(root, i)
try:
st = os.stat(current_dir)
st_mtime = st.st_mtime
except OSError:
st_mtime = 0
# do NOT follow symbolic links
if os.path.islink(current_dir):
l = self.__decode_filename(os.readlink(current_dir))
sql = """
insert into files(parent_id, filename, filepath, date, size, type)
values(?,?,?,?,?,?)
"""
db_cursor.execute(sql, (currentid, j + " -> " + l,
ocurrent_dir, st_mtime, 0,
self.LIN))
dirsize = 0
else:
dirsize = __recurse(currentid, j, current_dir,
st_mtime, 0, self.DIR, myit)
if dirsize == -1:
break
else:
_size = _size + dirsize
########
# files:
for i in files:
if self.abort:
break
self.count = self.count + 1
current_file = os.path.join(root, i)
try:
st = os.stat(current_file)
st_mtime = st.st_mtime
st_size = st.st_size
except OSError:
st_mtime = 0
st_size = 0
_size = _size + st_size
j = self.__decode_filename(i)
# do NOT follow symbolic links
if os.path.islink(current_file):
l = self.__decode_filename(os.readlink(current_file))
sql = """insert into files(parent_id, filename, filepath,
date, size, type)
values(?,?,?,?,?,?)"""
db_cursor.execute(sql, (currentid, j + " -> " + l,
current_file, st_mtime, 0,
self.LIN))
else:
sql = """
insert into files(parent_id, filename, filepath, date, size, type)
values(?,?,?,?,?,?)
"""
db_cursor.execute(sql, (currentid, j, current_file,
st_mtime, st_size, self.FIL))
if self.count % 32 == 0:
update = True
else:
update = False
###########################
# fetch details about files
if self.config.confd['retrive']:
update = True
exif = None
sql = """select seq FROM sqlite_sequence WHERE name='files'"""
db_cursor.execute(sql)
fileid = db_cursor.fetchone()[0]
ext = i.split('.')[-1].lower()
# Images - thumbnails and exif data
if self.config.confd['thumbs'] and ext in self.IMG:
tpath, exif, ret_code = Thumbnail(current_file, base=self.internal_dirname).save(fileid)
if ret_code != -1:
sql = """insert into thumbnails(file_id, filename) values (?, ?)"""
db_cursor.execute(sql, (fileid,
tpath.split(self.internal_dirname)[1][1:]))
# exif - stroe data in exif table
if self.config.confd['exif'] and ext in ['jpg', 'jpeg']:
p = None
if self.config.confd['thumbs'] and exif:
p = ParseExif(exif_dict=exif)
else:
p = ParseExif(exif_file=current_file)
if not p.exif_dict:
p = None
if p:
p = p.parse()
p = list(p)
p.insert(0, fileid)
sql = """INSERT INTO exif (file_id,
camera,
date,
aperture,
exposure_program,
exposure_bias,
iso,
focal_length,
subject_distance,
metering_mode,
flash,
light_source,
resolution,
orientation)
values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"""
db_cursor.execute(sql, (tuple(p)))
# Extensions - user defined actions
if ext in self.config.confd['extensions'].keys():
cmd = self.config.confd['extensions'][ext]
arg = string.replace(current_file, '"', '\\"')
output = os.popen(cmd % arg).readlines()
desc = ''
for line in output:
desc += line
#desc = string.replace(desc, "\n", "\\n")
sql = """update files set description=? where id=?"""
db_cursor.execute(sql, (desc, fileid))
#if i.split('.').[-1].lower() in mov_ext:
# # video only
# info = filetypeHelper.guess_video(os.path.join(root,i))
### end of scan
if update:
self.statusmsg = "Scannig: %s" % current_file
self.progress = step * self.count
sql = """update files set size=? where id=?"""
db_cursor.execute(sql,(_size, currentid))
if self.abort:
return -1
else:
return _size
if __recurse(1, self.label, self.path, 0, 0, self.DIR) == -1:
if __debug__:
print "m_main.py: __scan() __recurse()",
print "interrupted self.abort = True"
self.discs_tree.remove(self.fresh_disk_iter)
db_cursor.close()
db_connection.rollback()
else:
if __debug__:
print "m_main.py: __scan() __recurse() goes without interrupt"
if self.currentid:
if __debug__:
print "m_main.py: __scan() removing old branch"
self.delete(self.currentid, db_cursor, db_connection)
self.currentid = None
else:
print "new directory/cd"
db_cursor.close()
db_connection.commit()
db_connection.close()
if __debug__:
print "m_main.py: __scan() time: ", (datetime.now() - timestamp)
self.busy = False
# refresh discs tree
self.__fetch_db_into_treestore()
self.statusmsg = "Idle"
self.progress = 0
self.abort = False
def __fetch_db_into_treestore(self):
"""load data from DB to tree model"""
# cleanup treeStore
self.__clear_discs_tree()
#connect
db_connection = sqlite.connect("%s" % \
(self.internal_dirname + '/db.sqlite'),
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
db_cursor = db_connection.cursor()
# fetch all the directories
sql = """
SELECT id, parent_id, filename FROM files
WHERE type=1 ORDER BY parent_id, filename
"""
db_cursor.execute(sql)
data = db_cursor.fetchall()
try:
sql = """
SELECT id, parent_id, filename FROM files
WHERE type=1 ORDER BY parent_id, filename
"""
db_cursor.execute(sql)
data = db_cursor.fetchall()
except:
# cleanup
self.cleanup()
self.filename = None
self.internal_dirname = None
print "%s: Wrong database format!" % self.filename
return
def get_children(parent_id = 1, iterator = None):
"""fetch all children and place them in model"""
for row in data:
if row[1] == parent_id:
myiter = self.discs_tree.insert_before(iterator, None)
self.discs_tree.set_value(myiter, 0, row[0]) # id
self.discs_tree.set_value(myiter, 1, row[2]) # name
self.discs_tree.set_value(myiter, 3, row[1]) # parent_id
get_children(row[0], myiter)
# isroot?
if iterator == None:
self.discs_tree.set_value(myiter, 2, gtk.STOCK_CDROM)
else:
self.discs_tree.set_value(myiter, 2,
gtk.STOCK_DIRECTORY)
return
if __debug__:
start_date = datetime.now()
# launch scanning.
get_children()
if __debug__:
print "m_main.py: __fetch_db_into_treestore() tree generation time: ", (datetime.now() - start_date)
db_connection.close()
return
def __append_added_volume(self):
"""append branch from DB to existing tree model"""
#connect
db_connection = sqlite.connect("%s" %
(self.internal_dirname + '/db.sqlite'),
detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES)
db_cursor = db_connection.cursor()
sql = """SELECT id, parent_id, filename FROM files WHERE type=1 ORDER BY parent_id, filename"""
db_cursor.execute(sql)
data = db_cursor.fetchall()
def get_children(parent_id = 1, iterator = None):
"""fetch all children and place them in model"""
for row in data:
if row[1] == parent_id:
myiter = self.discs_tree.insert_before(iterator, None)
self.discs_tree.set_value(myiter, 0, row[0])
self.discs_tree.set_value(myiter, 1, row[2])
self.discs_tree.set_value(myiter, 3, row[1])
get_children(row[0], myiter)
# isroot?
if iterator == None:
self.discs_tree.set_value(myiter, 2, gtk.STOCK_CDROM)
else:
self.discs_tree.set_value(myiter, 2,
gtk.STOCK_DIRECTORY)
return
if __debug__:
start_date = datetime.now()
# launch scanning.
get_children()
if __debug__:
print "m_main.py: __append_added_volume() tree generation time: ", (datetime.now() - start_date)
db_connection.close()
return
def __decode_filename(self, txt):
if self.fsenc:
return txt.decode(self.fsenc)
else:
return txt
pass # end of class