1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-18 03:50:25 +01:00

* Added exteranl image viewer.

* Added edit for descriptions and notes for files.
 * Added possibility for make thumbnail for any directory/file.
 * More improvements and bufixes.
This commit is contained in:
2008-04-14 13:29:50 +00:00
parent 371f702f9d
commit 3fd3b2ec19
8 changed files with 400 additions and 162 deletions

View File

@@ -59,6 +59,8 @@ class ConfigController(Controller):
self.view['ch_gthumb'].set_active(self.model.confd['gthumb'])
self.view['ch_compress'].set_active(self.model.confd['compress'])
self.view['ch_retrive'].set_active(self.model.confd['retrive'])
self.view['ch_imageviewer'].set_active(self.model.confd['imgview'])
self.view['entry_imv'].set_text(self.model.confd['imgprog'])
self.__toggle_scan_group()
@@ -118,21 +120,30 @@ class ConfigController(Controller):
self.model.confd['gthumb'] = self.view['ch_gthumb'].get_active()
self.model.confd['compress'] = self.view['ch_compress'].get_active()
self.model.confd['retrive'] = self.view['ch_retrive'].get_active()
self.model.confd['imgview'] = self.view['ch_imageviewer'].get_active()
self.model.confd['imgprog'] = self.view['entry_imv'].get_text()
self.model.save()
self.view['config'].destroy()
return
def on_button_ejt_clicked(self, button):
self.__show_filechooser()
return
fn = self.__show_filechooser("Choose eject program")
self.view['ejt_entryentry_imv'].set_text(fn)
def on_button_mnt_clicked(self, button):
self.__show_dirchooser()
return
fn = self.__show_filechooser("Choose mount point")
self.view['mnt_entry'].set_text(fn)
def on_ch_retrive_toggled(self, widget):
self.__toggle_scan_group()
return
def on_ch_imageviewer_toggled(self, checkbox):
state = self.view['ch_imageviewer'].get_active()
for i in ['label_imv', 'entry_imv', 'button_imv']:
self.view[i].set_sensitive(state)
def on_button_imv_clicked(self, widget):
fn = self.__show_filechooser("Choose image viewer")
self.view['entry_imv'].set_text(fn)
def on_ext_add_clicked(self, widget):
ext = self.view['ext_entry'].get_text().lower()
@@ -220,10 +231,11 @@ class ConfigController(Controller):
column.set_resizable(True)
category_tree.append_column(column)
def __show_filechooser(self):
def __show_filechooser(self, title):
"""dialog for choose eject"""
fn = None
dialog = gtk.FileChooserDialog(
title="Choose eject program",
title=title,
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(
gtk.STOCK_CANCEL,
@@ -239,9 +251,9 @@ class ConfigController(Controller):
if response == gtk.RESPONSE_OK:
if __debug__:
print "c_config.py: __show_filechooser()", dialog.get_filename()
self.view['ejt_entry'].set_text(dialog.get_filename())
fn = dialog.get_filename()
dialog.destroy()
return fn
def __show_dirchooser(self):
"""dialog for point the mountpoint"""

View File

@@ -30,6 +30,7 @@ http://www.gnu.org/licenses/gpl.txt
"""
import os.path
from os import popen
from utils import deviceHelper
from gtkmvc import Controller
@@ -126,11 +127,83 @@ class MainController(Controller):
#########################################################################
# Connect signals from GUI, like menu objects, toolbar buttons and so on.
def on_edit2_activate(self, menu_item):
try:
selection = self.view['files'].get_selection()
model, list_of_paths = selection.get_selected_rows()
id = model.get_value(model.get_iter(list_of_paths[0]), 0)
except TypeError:
if __debug__: print "c_main.py: on_edit2_activate(): 0 zaznaczonych wierszy"
return
val = self.model.get_file_info(id)
ret = Dialogs.EditDialog(val).run()
if ret:
self.model.rename(id, ret['filename'])
self.model.update_desc_and_note(id, ret['description'], ret['note'])
self.__get_item_info(id)
def on_add_thumb1_activate(self, menu_item):
image = Dialogs.LoadImageFile().run()
if not image:
return
try:
selection = self.view['files'].get_selection()
model, list_of_paths = selection.get_selected_rows()
for path in list_of_paths:
id = model.get_value(model.get_iter(path),0)
self.model.add_thumbnail(image, id)
except:
if __debug__: print "c_main.py: on_add_thumb1_activate(): error on getting selected items or creating thumbnails"
return
self.__get_item_info(id)
return
def on_remove_thumb1_activate(self, menu_item):
if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete thumbnails', 'Delete thumbnails?',
'Thumbnails for selected items will be permanently removed from catalog.')
if not obj.run():
return
try:
selection = self.view['files'].get_selection()
model, list_of_paths = selection.get_selected_rows()
for path in list_of_paths:
id = model.get_value(model.get_iter(path),0)
self.model.del_thumbnail(id)
except:
if __debug__: print "c_main.py: on_remove_thumb1_activate(): error on getting selected items or removing thumbnails"
return
self.__get_item_info(id)
return
def on_remove_image1_activate(self, menu_item):
if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete images', 'Delete all images?',
'All images for selected items will be permanently removed from catalog.')
if not obj.run():
return
try:
selection = self.view['files'].get_selection()
model, list_of_paths = selection.get_selected_rows()
for path in list_of_paths:
id = model.get_value(model.get_iter(path),0)
self.model.del_images(id)
except:
if __debug__: print "c_main.py: on_remove_thumb1_activate(): error on getting selected items or removing thumbnails"
return
self.__get_item_info(id)
return
def on_images_item_activated(self, iconview, path):
model = iconview.get_model()
iter = model.get_iter(path)
id = model.get_value(iter, 0)
ImageView(self.model.get_image_path(id))
img = self.model.get_image_path(id)
if self.model.config.confd['imgview'] and len(self.model.config.confd['imgprog'])>0:
popen("%s %s" % (self.model.config.confd['imgprog'], img))
else:
ImageView(img)
def on_rename1_activate(self, widget):
model, iter = self.view['discs'].get_selection().get_selected()
@@ -138,8 +211,7 @@ class MainController(Controller):
id = model.get_value(iter, 0)
new_name = Dialogs.InputNewName(name).run()
if __debug__:
print "c_main.py: on_rename1_activate(): label:", new_name
if __debug__: print "c_main.py: on_rename1_activate(): label:", new_name
if new_name != None and new_name != name:
self.model.rename(id, new_name)
@@ -159,8 +231,7 @@ class MainController(Controller):
name = model.get_value(model.get_iter(list_of_paths[0]),1)
new_name = Dialogs.InputNewName(name).run()
if __debug__:
print "c_main.py: on_rename1_activate(): label:", new_name
if __debug__: print "c_main.py: on_rename1_activate(): label:", new_name
if new_name != None and new_name != name:
self.model.rename(fid, new_name)
@@ -176,8 +247,7 @@ class MainController(Controller):
return
def on_tag_cloud_textview_motion_notify_event(self, widget):
if __debug__:
print "c_main.py: on_tag_cloud_textview_motion_notify_event():"
if __debug__: print "c_main.py: on_tag_cloud_textview_motion_notify_event():"
w = self.view['tag_cloud_textview'].get_window(gtk.TEXT_WINDOW_TEXT)
if w:
w.set_cursor(None)
@@ -322,6 +392,10 @@ class MainController(Controller):
def on_img_add_activate(self, menu_item):
self.on_add_image1_activate(menu_item)
def on_thumb_box_button_press_event(self, widget, event):
if event.button == 3:
self.__popup_menu(event, 'th_popup')
def on_discs_button_press_event(self, treeview, event):
try:
path, column, x, y = treeview.get_path_at_pos(int(event.x),
@@ -379,9 +453,11 @@ class MainController(Controller):
if len(list_of_paths) > 1:
self.view['add_image1'].set_sensitive(False)
self.view['rename2'].set_sensitive(False)
self.view['edit2'].set_sensitive(False)
else:
self.view['add_image1'].set_sensitive(True)
self.view['rename2'].set_sensitive(True)
self.view['edit2'].set_sensitive(True)
self.__popup_menu(event, 'files_popup')
return True
@@ -394,8 +470,7 @@ class MainController(Controller):
selected_item = self.model.files_list.get_value(iter, 0)
self.__get_item_info(selected_item)
except:
if __debug__:
print "c_main.py: on_files_cursor_changed() insufficient iterator"
if __debug__: print "c_main.py: on_files_cursor_changed() insufficient iterator"
return
def on_files_key_release_event(self, a, event):
@@ -470,9 +545,10 @@ class MainController(Controller):
print self.view['files'].get_cursor()
def on_add_image1_activate(self, menu_item):
images = Dialogs.LoadImageFile().run()
images = Dialogs.LoadImageFile(True).run()
if not images:
return
for image in images:
try:
selection = self.view['files'].get_selection()
@@ -561,7 +637,7 @@ class MainController(Controller):
if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete elements', 'Delete items?',
'Items will be permanently removed.')
'Items will be permanently removed from catalog.')
if not obj.run():
return
@@ -590,11 +666,27 @@ class MainController(Controller):
self.model.get_root_entries(model.get_value(model.get_iter(list_of_paths[0]),0))
except TypeError:
return
buf = gtk.TextBuffer()
self.view['description'].set_buffer(buf)
self.view['thumb_box'].hide()
self.view['exifinfo'].hide()
self.view['img_container'].hide()
self.model.unsaved_project = True
self.__set_title(filepath=self.model.filename, modified=True)
return
def on_th_delete_activate(self, menu_item):
path, column = self.view['files'].get_cursor()
model = self.view['files'].get_model()
iter = model.get_iter(path)
id = model.get_value(iter, 0)
if id:
self.model.del_thumbnail(id)
self.__get_item_info(id)
return
def on_debugbtn_clicked(self, widget):
"""Debug. To remove in stable version, including button in GUI"""
if __debug__:
@@ -762,8 +854,6 @@ class MainController(Controller):
buf = self.view['description'].get_buffer()
buf.set_text("")
self.view['description'].set_buffer(buf)
self.view['thumb'].hide()
self.__activate_ui()
return
@@ -903,18 +993,47 @@ class MainController(Controller):
def __get_item_info(self, item):
self.view['description'].show()
set = self.model.get_file_info(item)
buf = self.view['description'].get_buffer()
buf = gtk.TextBuffer()
if set.has_key('file_info'):
buf.set_text(set['file_info'])
if set.has_key('description'):
tag = buf.create_tag()
tag.set_property('weight', pango.WEIGHT_BOLD)
buf.insert_with_tags(buf.get_end_iter(), "\nDetails:\n", tag)
buf.insert(buf.get_end_iter(), set['description'])
else:
buf.set_text('')
if __debug__ and set.has_key('debug'):
tag = buf.create_tag()
tag.set_property('weight', pango.WEIGHT_BOLD)
buf.insert_with_tags(buf.get_end_iter(), "ID: ", tag)
buf.insert(buf.get_end_iter(), str(set['debug']['id']) + "\n")
buf.insert_with_tags(buf.get_end_iter(), "Filename: ", tag)
buf.insert(buf.get_end_iter(), set['filename'] + "\n")
buf.insert_with_tags(buf.get_end_iter(), "Date: ", tag)
buf.insert(buf.get_end_iter(), str(set['debug']['date']) + "\n")
buf.insert_with_tags(buf.get_end_iter(), "Size: ", tag)
buf.insert(buf.get_end_iter(), str(set['debug']['size']) + "\n")
buf.insert_with_tags(buf.get_end_iter(), "Type: ", tag)
buf.insert(buf.get_end_iter(), str(set['debug']['type']) + "\n\n")
if set.has_key('gthumb'):
tag = buf.create_tag()
tag.set_property('weight', pango.WEIGHT_BOLD)
buf.insert_with_tags(buf.get_end_iter(), "gThumb comment:\n", tag)
if set['gthumb']['note']:
buf.insert(buf.get_end_iter(), set['gthumb']['note'] + "\n")
if set['gthumb']['place']:
buf.insert(buf.get_end_iter(), set['gthumb']['place'] + "\n")
if set['gthumb']['date']:
buf.insert(buf.get_end_iter(), set['gthumb']['date'] + "\n")
buf.insert(buf.get_end_iter(), "\n")
if set.has_key('description'):
tag = buf.create_tag()
tag.set_property('weight', pango.WEIGHT_BOLD)
buf.insert_with_tags(buf.get_end_iter(), "Details:\n", tag)
buf.insert(buf.get_end_iter(), set['description'])
buf.insert(buf.get_end_iter(), "\n")
if set.has_key('note'):
tag = buf.create_tag()
tag.set_property('weight', pango.WEIGHT_BOLD)
buf.insert_with_tags(buf.get_end_iter(), "Note:\n", tag)
buf.insert(buf.get_end_iter(), set['note'])
self.view['description'].set_buffer(buf)
if set.has_key('images'):
@@ -931,9 +1050,11 @@ class MainController(Controller):
if set.has_key('thumbnail'):
self.view['thumb'].set_from_file(set['thumbnail'])
self.view['thumb'].show()
self.view['thumb_box'].show()
#self.view['thumb'].show()
else:
self.view['thumb'].hide()
#self.view['thumb'].hide()
self.view['thumb_box'].hide()
return
def __tag_cloud(self):
@@ -953,7 +1074,6 @@ class MainController(Controller):
self.view['tag_cloud_textview'].get_window(gtk.TEXT_WINDOW_TEXT)
if w:
w.set_cursor(None)
def insert_blank(b, iter):
if iter.is_end() and iter.is_start():

View File

@@ -78,6 +78,9 @@ class ConfigModel(Model):
'cd': '/mnt/cdrom',
'ejectapp': 'eject -r',
'imgview': False,
'imgprog': 'gqview',
'retrive': False,
'thumbs': True,
@@ -122,6 +125,8 @@ class ConfigModel(Model):
'retrive extra informatin':'retrive',
'scan exif data':'exif',
'include gthumb image description':'gthumb',
'use external image viewer':'imgview',
'external image viewer program':'imgprog',
}
dbool = (
@@ -141,12 +146,13 @@ class ConfigModel(Model):
'delwarn',
'compress',
'retrive',
'imgview',
)
recent = []
RECENT_MAX = 10
dstring = ('cd','ejectapp')
dstring = ('cd','ejectapp','imgprog')
try:
path = os.environ['HOME']

View File

@@ -45,8 +45,11 @@ except ImportError:
from m_config import ConfigModel
from m_details import DetailsModel
from utils.thumbnail import Thumbnail
from utils.img import Img
try:
from utils.thumbnail import Thumbnail
from utils.img import Img
except:
pass
from utils.parse_exif import ParseExif
from utils.gthumb import GthumbCommentParser
@@ -131,7 +134,9 @@ class MainModel(ModelMT):
{'id': str(10), 'name': "windows", 'size': 18, 'color': '#333'},
]'''
return
def add_image(self, image, id):
"""add single image to file/directory"""
sql = """insert into images(file_id, thumbnail, filename)
values(?, null, null)"""
self.db_cursor.execute(sql, (id,))
@@ -148,8 +153,72 @@ class MainModel(ModelMT):
(ip.split(self.internal_dirname)[1][1:],
tp.split(self.internal_dirname)[1][1:],
res[0]))
self.db_connection.commit()
self.db_connection.commit()
def del_images(self, id):
"""removes images and their thumbnails from selected file/dir"""
# remove images
sql = """select filename, thumbnail from images where file_id =?"""
self.db_cursor.execute(sql, (id,))
res = self.db_cursor.fetchall()
if len(res) > 0:
for fn in res:
os.unlink(os.path.join(self.internal_dirname, fn[0]))
os.unlink(os.path.join(self.internal_dirname, fn[1]))
# remove images records
sql = """delete from images where file_id = ?"""
self.db_cursor.execute(sql, (id,))
self.db_connection.commit()
def delete_image(self, id):
"""removes image on specified image 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 add_thumbnail(self, img_fn, id):
"""generate and add thumbnail to selected file/dir"""
if self.config.confd['thumbs']:
self.del_thumbnail(id)
p, e, ret_code = Thumbnail(img_fn,
base=self.internal_dirname).save(id)
if ret_code != -1:
sql = """insert into thumbnails(file_id, filename) values (?, ?)"""
self.db_cursor.execute(sql,
(id,
p.split(self.internal_dirname)[1][1:]))
self.db_connection.commit()
return True
return False
def del_thumbnail(self, id):
"""removes thumbnail from selected file/dir"""
# remove thumbnail files
sql = """select filename from thumbnails where file_id=?"""
self.db_cursor.execute(sql, (id,))
res = self.db_cursor.fetchone()
if res:
os.unlink(os.path.join(self.internal_dirname, res[0]))
# remove thumbs records
sql = """delete from thumbnails where file_id=?"""
self.db_cursor.execute(sql, (id,))
self.db_connection.commit()
def cleanup(self):
self.__close_db_connection()
if self.internal_dirname != None:
@@ -202,7 +271,8 @@ class MainModel(ModelMT):
os.chdir(self.internal_dirname)
try:
tar.extractall()
print "m_main.py: extracted tarfile into", self.internal_dirname
if __debug__:
print "m_main.py: extracted tarfile into", self.internal_dirname
except AttributeError:
# python's 2.4 tarfile module lacks of method extractall()
directories = []
@@ -328,18 +398,24 @@ class MainModel(ModelMT):
"""get file info from database"""
retval = {}
sql = """SELECT f.filename, f.date, f.size, f.type,
t.filename, f.description
t.filename, f.description, f.note
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
retval['debug'] = {'id': id,
'date': datetime.fromtimestamp(set[1]),
'size': set[2], 'type': set[3]}
retval['filename'] = set[0]
if set[5]:
retval['description'] = set[5]
if set[6]:
retval['note'] = set[6]
if set[4]:
retval['thumbnail'] = os.path.join(self.internal_dirname, set[4])
@@ -370,8 +446,16 @@ class MainModel(ModelMT):
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
# gthumb
sql = """SELECT note, place, date from gthumb WHERE file_id = ?"""
self.db_cursor.execute(sql, (id,))
set = self.db_cursor.fetchone()
if set:
retval['gthumb'] = {'note': set[0], 'place': set[1], 'date': set[2]}
return retval
def get_source(self, path):
@@ -396,27 +480,10 @@ class MainModel(ModelMT):
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"""
remove all possible data, like thumbnails, images, gthumb info, exif
etc"""
fids = []
@@ -429,9 +496,7 @@ class MainModel(ModelMT):
sql = """select parent_id from files where id = ?"""
db_cursor.execute(sql, (root_id,))
res = db_cursor.fetchone()
if res:
parent_id = res[0]
parent_id = res[0]
def get_children(fid):
fids.append(fid)
@@ -456,13 +521,9 @@ class MainModel(ModelMT):
sql = """delete from tags_files where file_id = ?"""
db_cursor.executemany(sql, generator())
arg = self.__list_to_string(fids)
# 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()
@@ -477,6 +538,7 @@ class MainModel(ModelMT):
if len(res) > 0:
for fn in res:
os.unlink(os.path.join(self.internal_dirname, fn[0]))
os.unlink(os.path.join(self.internal_dirname, fn[1]))
# remove thumbs records
sql = """delete from thumbnails where file_id = ?"""
@@ -486,6 +548,10 @@ class MainModel(ModelMT):
sql = """delete from images where file_id = ?"""
db_cursor.executemany(sql, generator())
# remove gthumb info
sql = """delete from gthumb where file_id = ?"""
db_cursor.executemany(sql, generator())
# correct parent direcotry sizes
# get size and parent of deleting object
while parent_id:
@@ -500,8 +566,6 @@ class MainModel(ModelMT):
from files where parent_id=?) where id=?"""
db_cursor.execute(sql, (parent_id, parent_id))
sql = """select parent_id from files where id = ? and parent_id!=id"""
db_cursor.execute(sql, (parent_id,))
res = db_cursor.fetchone()
@@ -590,9 +654,15 @@ class MainModel(ModelMT):
self.db_cursor.execute(sql, (img_id,))
res = self.db_cursor.fetchone()
if res:
return res[0]
return os.path.join(self.internal_dirname, res[0])
return None
def update_desc_and_note(self, id, desc='', note=''):
"""update note and description"""
sql = """UPDATE files SET description=?, note=? WHERE id=?"""
self.db_cursor.execute(sql, (desc, note, id))
return
# private class functions
def __bytes_to_human(self, integer):
if integer <= 0 or integer < 1024:
@@ -729,6 +799,7 @@ class MainModel(ModelMT):
date datetime);""")
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');")
self.db_connection.commit()
def __scan(self):
"""scan content of the given path"""
@@ -952,7 +1023,7 @@ class MainModel(ModelMT):
cmnts['place'],
cmnts['date']
))
if cmnts['keywords']:
if cmnts.has_key('keywords'):
# TODO: add gthumb keywords to tags and group 'gthumb'
pass
@@ -997,7 +1068,9 @@ class MainModel(ModelMT):
if self.currentid:
if __debug__:
print "m_main.py: __scan() removing old branch"
self.statusmsg = "Removing old branch..."
self.delete(self.currentid, db_cursor, db_connection)
self.currentid = None
else:
print "new directory/cd"
@@ -1120,4 +1193,12 @@ class MainModel(ModelMT):
else:
return txt
def __list_to_string(self, array):
arg =''
for c in array:
if len(arg) > 0:
arg+=", %d" % c
else:
arg = "%d" % c
return arg
pass # end of class

View File

@@ -1,3 +1,26 @@
# 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
# -------------------------------------------------------------------------
from xml.dom.minidom import Node
from xml.dom import minidom
import gzip

View File

@@ -27,7 +27,6 @@ from shutil import move, copy
from os import path, mkdir
from datetime import datetime
from utils import EXIF
import Image
class Img(object):
@@ -40,76 +39,26 @@ class Img(object):
def save(self, image_id):
"""Save image and asociated thumbnail into specific directory structure
return full path to the file and thumbnail None"""
return full path to the file and thumbnail or None"""
base_path = self.__get_and_make_path(image_id)
ext = self.filename.split('.')[-1].lower()
image_filename = path.join(self.base, base_path + "_im." + ext)
image_filename = path.join(self.base, base_path + "." + ext)
thumbnail = path.join(self.base, base_path + "_t.jpg")
# make and save image
filepath = path.join(self.base, base_path + ".jpg")
f = open(self.filename, 'rb')
exif = None
returncode = -1
try:
exif = EXIF.process_file(f)
f.close()
if exif.has_key('JPEGThumbnail'):
thumbnail = exif['JPEGThumbnail']
f = open(filepath,'wb')
f.write(thumbnail)
f.close()
if exif.has_key('Image Orientation'):
orientation = exif['Image Orientation'].values[0]
if orientation > 1:
# TODO: replace silly datetime function with tempfile
t = path.join(gettempdir(), "thumb%d.jpg" % datetime.now().microsecond)
im_in = Image.open(filepath)
im_out = None
if orientation == 8:
# Rotated 90 CCW
im_out = im_in.transpose(Image.ROTATE_90)
elif orientation == 6:
# Rotated 90 CW
im_out = im_in.transpose(Image.ROTATE_270)
elif orientation == 3:
# Rotated 180
im_out = im_in.transpose(Image.ROTATE_180)
elif orientation == 2:
# Mirrored horizontal
im_out = im_in.transpose(Image.FLIP_LEFT_RIGHT)
elif orientation == 4:
# Mirrored vertical
im_out = im_in.transpose(Image.FLIP_TOP_BOTTOM)
elif orientation == 5:
# Mirrored horizontal then rotated 90 CCW
im_out = im_in.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_90)
elif orientation == 7:
# Mirrored horizontal then rotated 90 CW
im_out = im_in.transpose(Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_270)
if im_out:
im_out.save(t, 'JPEG')
move(t, filepath)
else:
f.close()
returncode = 0
else:
im = self.__scale_image()
if im:
im.save(filepath, "JPEG")
returncode = 1
except:
f.close()
im = self.__scale_image()
if im:
im.save(filepath, "JPEG")
returncode = 2
im = self.__scale_image()
if im:
im.save(thumbnail, "JPEG")
returncode = 1
if returncode != -1:
# copy image
copy(self.filename, image_filename)
return filepath, image_filename, returncode
return thumbnail, image_filename, returncode
# private class functions
def __get_and_make_path(self, img_id):
@@ -146,7 +95,7 @@ class Img(object):
img = "%s" % h[2:]
return(path.join(t, fpath, img))
def __scale_image(self, factor=True):
def __scale_image(self):
"""create thumbnail. returns image object or None"""
try:
im = Image.open(self.filename).convert('RGB')

View File

@@ -177,14 +177,15 @@ class PointDirectoryToAdd(object):
dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
dialog.set_default_response(gtk.RESPONSE_OK)
if self.URI:
dialog.set_current_folder_uri(self.URI)
response = dialog.run()
if response == gtk.RESPONSE_OK:
self.directory.set_text(dialog.get_filename())
self.__class__.URI = dialog.get_current_folder_uri()
dialog.destroy()
def run(self):
if self.URI:
self.dialog.set_current_folder_uri(self.URI)
dialog = self.gladexml.get_widget("addDirDialog")
ch = True
result = dialog.run()
@@ -195,7 +196,6 @@ class PointDirectoryToAdd(object):
result = dialog.run()
else:
ch = False
self.__class__.URI = self.dialog.get_current_folder_uri()
dialog.destroy()
if result == gtk.RESPONSE_OK:
return self.volname.get_text(),self.directory.get_text()
@@ -321,7 +321,7 @@ class LoadImageFile(object):
URI="file://"+os.path.abspath(os.path.curdir)
def __init__(self):
def __init__(self, multiple=False):
self.dialog = gtk.FileChooserDialog(
title="Select image",
action=gtk.FILE_CHOOSER_ACTION_OPEN,
@@ -332,7 +332,7 @@ class LoadImageFile(object):
gtk.RESPONSE_OK
)
)
self.dialog.set_select_multiple(True)
self.dialog.set_select_multiple(multiple)
self.dialog.set_default_response(gtk.RESPONSE_OK)
f = gtk.FileFilter()
@@ -357,7 +357,10 @@ class LoadImageFile(object):
if response == gtk.RESPONSE_OK:
try:
filenames = self.dialog.get_filenames()
if self.dialog.get_select_multiple():
filenames = self.dialog.get_filenames()
else:
filenames = self.dialog.get_filename()
except:
pass
@@ -417,3 +420,41 @@ class StatsDialog(object):
if result == gtk.RESPONSE_OK:
return entry.get_text()
return None
class EditDialog(object):
"""Sepcific dialog for display stats"""
def __init__(self, values={}):
self.gladefile = os.path.join(utils.globals.GLADE_DIR, "dialogs.glade")
self.values = values
def run(self):
gladexml = gtk.glade.XML(self.gladefile, "file_editDialog")
dialog = gladexml.get_widget("file_editDialog")
filename = gladexml.get_widget("filename_entry")
filename.set_text(str(self.values['filename']))
description = gladexml.get_widget("description_text")
note = gladexml.get_widget("note_text")
if self.values.has_key('description'):
buff = gtk.TextBuffer()
buff.set_text(str(self.values['description']))
description.set_buffer(buff)
if self.values.has_key('note'):
buff = gtk.TextBuffer()
buff.set_text(str(self.values['note']))
note.set_buffer(buff)
result = dialog.run()
if result == gtk.RESPONSE_OK:
d = description.get_buffer()
n = note.get_buffer()
retval = {'filename': filename.get_text(),
'description': d.get_text(d.get_start_iter(),
d.get_end_iter()),
'note': n.get_text(n.get_start_iter(), n.get_end_iter())}
dialog.destroy()
return retval
dialog.destroy()
return None