mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 11:30:19 +01:00
* Added thumbnals generating for images.
* Lots of fixes.
This commit is contained in:
@@ -89,16 +89,57 @@
|
|||||||
<property name="column_spacing">3</property>
|
<property name="column_spacing">3</property>
|
||||||
<property name="row_spacing">3</property>
|
<property name="row_spacing">3</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkLabel" id="label5">
|
<widget class="GtkLabel" id="label4">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes">Eject program:</property>
|
<property name="label" translatable="yes">Mount point:</property>
|
||||||
<property name="mnemonic_widget">ejt_entry</property>
|
<property name="mnemonic_widget">mnt_entry</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
|
<property name="x_options"></property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="mnt_entry">
|
||||||
|
<property name="width_request">100</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkButton" id="button_mnt">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="label" translatable="yes">Browse...</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="response_id">0</property>
|
||||||
|
<signal name="clicked" handler="on_button_mnt_clicked"/>
|
||||||
|
<signal name="activate" handler="on_button_mnt_activate"/>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">2</property>
|
||||||
|
<property name="right_attach">3</property>
|
||||||
|
<property name="x_options"></property>
|
||||||
|
<property name="y_options"></property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="ejt_entry">
|
||||||
|
<property name="width_request">100</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="right_attach">2</property>
|
||||||
<property name="top_attach">1</property>
|
<property name="top_attach">1</property>
|
||||||
<property name="bottom_attach">2</property>
|
<property name="bottom_attach">2</property>
|
||||||
<property name="x_options"></property>
|
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
@@ -122,56 +163,15 @@
|
|||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkEntry" id="ejt_entry">
|
<widget class="GtkLabel" id="label5">
|
||||||
<property name="width_request">100</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="right_attach">2</property>
|
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="bottom_attach">2</property>
|
|
||||||
<property name="y_options"></property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkButton" id="button_mnt">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="label" translatable="yes">Browse...</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
<property name="response_id">0</property>
|
|
||||||
<signal name="clicked" handler="on_button_mnt_clicked"/>
|
|
||||||
<signal name="activate" handler="on_button_mnt_activate"/>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">2</property>
|
|
||||||
<property name="right_attach">3</property>
|
|
||||||
<property name="x_options"></property>
|
|
||||||
<property name="y_options"></property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkEntry" id="mnt_entry">
|
|
||||||
<property name="width_request">100</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="right_attach">2</property>
|
|
||||||
<property name="y_options"></property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<widget class="GtkLabel" id="label4">
|
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="xalign">0</property>
|
<property name="xalign">0</property>
|
||||||
<property name="label" translatable="yes">Mount point:</property>
|
<property name="label" translatable="yes">Eject program:</property>
|
||||||
<property name="mnemonic_widget">mnt_entry</property>
|
<property name="mnemonic_widget">ejt_entry</property>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="bottom_attach">2</property>
|
||||||
<property name="x_options"></property>
|
<property name="x_options"></property>
|
||||||
<property name="y_options"></property>
|
<property name="y_options"></property>
|
||||||
</packing>
|
</packing>
|
||||||
@@ -554,7 +554,19 @@ Movies extesions</property>
|
|||||||
<property name="n_columns">2</property>
|
<property name="n_columns">2</property>
|
||||||
<property name="row_spacing">3</property>
|
<property name="row_spacing">3</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkEntry" id="ext_add">
|
<widget class="GtkLabel" id="label12">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
|
<property name="label" translatable="yes">Extension:</property>
|
||||||
|
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
||||||
|
<property name="mnemonic_widget">ext_entry</property>
|
||||||
|
</widget>
|
||||||
|
<packing>
|
||||||
|
<property name="x_options">GTK_FILL</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkEntry" id="ext_entry">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
@@ -564,18 +576,6 @@ Movies extesions</property>
|
|||||||
<property name="right_attach">2</property>
|
<property name="right_attach">2</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<widget class="GtkLabel" id="label12">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<property name="label" translatable="yes">Extension:</property>
|
|
||||||
<property name="justify">GTK_JUSTIFY_RIGHT</property>
|
|
||||||
<property name="mnemonic_widget">ext_add</property>
|
|
||||||
</widget>
|
|
||||||
<packing>
|
|
||||||
<property name="x_options">GTK_FILL</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
@@ -589,23 +589,25 @@ Movies extesions</property>
|
|||||||
<property name="border_width">3</property>
|
<property name="border_width">3</property>
|
||||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkButton" id="button1">
|
<widget class="GtkButton" id="ext_add">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label" translatable="yes">Add</property>
|
<property name="label" translatable="yes">Add</property>
|
||||||
<property name="response_id">0</property>
|
<property name="response_id">0</property>
|
||||||
|
<signal name="clicked" handler="on_ext_add_clicked"/>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkButton" id="button2">
|
<widget class="GtkButton" id="ext_del">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="receives_default">True</property>
|
<property name="receives_default">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="label" translatable="yes">Delete</property>
|
<property name="label" translatable="yes">Delete</property>
|
||||||
<property name="response_id">0</property>
|
<property name="response_id">0</property>
|
||||||
|
<signal name="clicked" handler="on_ext_del_clicked"/>
|
||||||
</widget>
|
</widget>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
@@ -630,7 +632,6 @@ Movies extesions</property>
|
|||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="can_focus">True</property>
|
<property name="can_focus">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||||
<property name="headers_clickable">True</property>
|
|
||||||
<property name="rules_hint">True</property>
|
<property name="rules_hint">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
|
|||||||
@@ -233,11 +233,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkSeparatorMenuItem" id="separator4">
|
|
||||||
|
<widget class="GtkSeparatorMenuItem" id="separatormenuitem4">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
|
||||||
<property name="label" translatable="yes">menuitem1</property>
|
|
||||||
<property name="use_underline">True</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
@@ -259,6 +257,7 @@
|
|||||||
<property name="label" translatable="yes">Thumbnails</property>
|
<property name="label" translatable="yes">Thumbnails</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
<property name="draw_as_radio">True</property>
|
<property name="draw_as_radio">True</property>
|
||||||
|
<property name="group">list1</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
from gtkmvc import Controller
|
from gtkmvc import Controller
|
||||||
|
import views.v_dialogs as Dialogs
|
||||||
|
|
||||||
import gtk
|
import gtk
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ class ConfigController(Controller):
|
|||||||
# initialize models for files extensions
|
# initialize models for files extensions
|
||||||
self.view['ext_choose'].set_model(self.model.ext_list)
|
self.view['ext_choose'].set_model(self.model.ext_list)
|
||||||
self.view['ext_choose'].set_active(0)
|
self.view['ext_choose'].set_active(0)
|
||||||
|
self.view['extension_tree'].get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
||||||
self.view['config'].show();
|
self.view['config'].show();
|
||||||
return
|
return
|
||||||
# Podłącz sygnały:
|
# Podłącz sygnały:
|
||||||
@@ -125,6 +126,50 @@ class ConfigController(Controller):
|
|||||||
return
|
return
|
||||||
|
|
||||||
def on_ext_choose_changed(self, widget):
|
def on_ext_choose_changed(self, widget):
|
||||||
|
self.__setup_extension_tree()
|
||||||
|
self.view['ext_entry'].set_text('')
|
||||||
|
return
|
||||||
|
|
||||||
|
def on_ext_add_clicked(self, widget):
|
||||||
|
ext = self.view['ext_entry'].get_text().lower()
|
||||||
|
if len(ext) == 0:
|
||||||
|
Dialogs.Err("Config - pyGTKtalog", "Error", "Extension is empty")
|
||||||
|
return
|
||||||
|
if self.view['ext_choose'].get_active() == 0:
|
||||||
|
if ext not in self.model.confd['img_ext']:
|
||||||
|
self.model.confd['img_ext'].append(ext)
|
||||||
|
self.model.refresh_ext('img_ext')
|
||||||
|
else:
|
||||||
|
self.model.confd['mov_ext'].append(ext)
|
||||||
|
|
||||||
|
self.__setup_extension_tree()
|
||||||
|
return
|
||||||
|
|
||||||
|
def on_ext_del_clicked(self, widget):
|
||||||
|
model, selection = self.view['extension_tree'].get_selection().get_selected_rows()
|
||||||
|
if len(selection) == 0:
|
||||||
|
Dialogs.Err("Config - pyGTKtalog", "Error", "No item selected")
|
||||||
|
return
|
||||||
|
elif len(selection) == 1:
|
||||||
|
sufix = ''
|
||||||
|
else:
|
||||||
|
sufix = "s"
|
||||||
|
|
||||||
|
if self.model.confd['delwarn']:
|
||||||
|
obj = Dialogs.Qst('Delete extension%s' % sufix,
|
||||||
|
'Delete extension%s?' % sufix,
|
||||||
|
'Object%s will be permanently removed.' % sufix)
|
||||||
|
if not obj.run():
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.view['ext_choose'].get_active() == 0:
|
||||||
|
n = 'img_ext'
|
||||||
|
else:
|
||||||
|
n = 'mov_ext'
|
||||||
|
|
||||||
|
for i in selection:
|
||||||
|
self.model.confd[n].remove(model.get_value(model.get_iter(i), 0))
|
||||||
|
|
||||||
self.__setup_extension_tree()
|
self.__setup_extension_tree()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -132,9 +177,11 @@ class ConfigController(Controller):
|
|||||||
# private controller methods
|
# private controller methods
|
||||||
def __setup_extension_tree(self):
|
def __setup_extension_tree(self):
|
||||||
if self.view['ext_choose'].get_active() == 0:
|
if self.view['ext_choose'].get_active() == 0:
|
||||||
self.view['extension_tree'].set_model(self.model.images_tree)
|
self.model.refresh_ext('img_ext')
|
||||||
else:
|
else:
|
||||||
self.view['extension_tree'].set_model(self.model.movies_tree)
|
self.model.refresh_ext('mov_ext')
|
||||||
|
|
||||||
|
self.view['extension_tree'].set_model(self.model.ext_tree)
|
||||||
|
|
||||||
for i in self.view['extension_tree'].get_columns():
|
for i in self.view['extension_tree'].get_columns():
|
||||||
self.view['extension_tree'].remove_column(i)
|
self.view['extension_tree'].remove_column(i)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class ConfigModel(Model):
|
|||||||
|
|
||||||
__properties__ = {}
|
__properties__ = {}
|
||||||
|
|
||||||
extensions_list = ['Images extensions', 'Movies extesions']
|
filetype_list = ['Images', 'Movies']
|
||||||
|
|
||||||
confd = {
|
confd = {
|
||||||
'savewin': True,
|
'savewin': True,
|
||||||
@@ -65,24 +65,30 @@ class ConfigModel(Model):
|
|||||||
'wy': 600,
|
'wy': 600,
|
||||||
'h': 200,
|
'h': 200,
|
||||||
'v': 300,
|
'v': 300,
|
||||||
|
'eject': True,
|
||||||
|
'compress': True,
|
||||||
|
|
||||||
'exportxls': False,
|
'exportxls': False,
|
||||||
|
|
||||||
|
'confirmquit': True,
|
||||||
|
'confirmabandon': True,
|
||||||
|
'mntwarn': True,
|
||||||
|
'delwarn': True,
|
||||||
|
|
||||||
'cd': '/cdrom',
|
'cd': '/cdrom',
|
||||||
'ejectapp': 'eject -r',
|
'ejectapp': 'eject -r',
|
||||||
'eject' : True,
|
|
||||||
'thumbs': False,
|
'retrive': False,
|
||||||
|
|
||||||
|
'thumbs': True,
|
||||||
|
'exif': True,
|
||||||
'gthumb': False,
|
'gthumb': False,
|
||||||
'exif':False,
|
|
||||||
'confirmquit':True,
|
'mov_ext': ['avi', 'mkv', 'mpg', 'mpeg', 'wmv'],
|
||||||
'mntwarn':True,
|
'img_ext': ['bmp', 'gif', 'jpg', 'jpeg', 'png'],
|
||||||
'confirmabandon':True,
|
|
||||||
'showtoolbar':True,
|
'showtoolbar':True,
|
||||||
'showstatusbar':True,
|
'showstatusbar':True,
|
||||||
'delwarn':True,
|
|
||||||
'compress':True,
|
|
||||||
'compress':True,
|
|
||||||
'retrive':False,
|
|
||||||
'mov_ext':['mkv', 'avi', 'ogg', 'mpg', 'wmv', 'mp4', 'mpeg'],
|
|
||||||
'img_ext':['jpg','jpeg','png','gif','bmp','tga','tif','tiff','ilbm','iff','pcx'],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dictconf = {
|
dictconf = {
|
||||||
@@ -141,27 +147,27 @@ class ConfigModel(Model):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
Model.__init__(self)
|
Model.__init__(self)
|
||||||
self.category_tree = gtk.ListStore(gobject.TYPE_STRING)
|
self.category_tree = gtk.ListStore(gobject.TYPE_STRING)
|
||||||
self.images_tree = gtk.ListStore(gobject.TYPE_STRING)
|
|
||||||
self.confd['img_ext'].sort()
|
|
||||||
for i in self.confd['img_ext']:
|
|
||||||
myiter = self.images_tree.insert_before(None,None)
|
|
||||||
self.images_tree.set_value(myiter,0,i)
|
|
||||||
self.movies_tree = gtk.ListStore(gobject.TYPE_STRING)
|
|
||||||
self.confd['mov_ext'].sort()
|
|
||||||
for i in self.confd['mov_ext']:
|
|
||||||
myiter = self.movies_tree.insert_before(None,None)
|
|
||||||
self.movies_tree.set_value(myiter,0,i)
|
|
||||||
|
|
||||||
self.ext_list = gtk.ListStore(gobject.TYPE_STRING)
|
self.ext_list = gtk.ListStore(gobject.TYPE_STRING)
|
||||||
for i in self.extensions_list:
|
for i in self.filetype_list:
|
||||||
myiter = self.ext_list.insert_before(None,None)
|
myiter = self.ext_list.insert_before(None,None)
|
||||||
self.ext_list.set_value(myiter,0,i)
|
self.ext_list.set_value(myiter,0,i)
|
||||||
|
|
||||||
|
self.refresh_ext('img_ext')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_ext(self, key):
|
||||||
|
self.ext_tree = gtk.ListStore(gobject.TYPE_STRING)
|
||||||
|
self.confd[key].sort()
|
||||||
|
for i in self.confd[key]:
|
||||||
|
myiter = self.ext_tree.insert_before(None,None)
|
||||||
|
self.ext_tree.set_value(myiter,0,i)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
try:
|
try:
|
||||||
os.lstat("%s/.pygtktalog" % self.path)
|
os.lstat("%s/.pygtktalog" % self.path)
|
||||||
except:
|
except:
|
||||||
|
print "Saving preferences to %s/.pygtktalog" % self.path
|
||||||
if __debug__:
|
if __debug__:
|
||||||
print "m_config.py: save() Saving preferences to %s/.pygtktalog" % self.path
|
print "m_config.py: save() Saving preferences to %s/.pygtktalog" % self.path
|
||||||
newIni = Ini()
|
newIni = Ini()
|
||||||
|
|||||||
@@ -55,9 +55,159 @@ from m_config import ConfigModel
|
|||||||
from m_details import DetailsModel
|
from m_details import DetailsModel
|
||||||
|
|
||||||
class Thumbnail(object):
|
class Thumbnail(object):
|
||||||
def __init__(self, *args):
|
def __init__(self, filename=None, x=160, y=120, root='thumbnails', base=''):
|
||||||
self.x = None
|
self.root = root
|
||||||
self.y = None
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.filename = filename
|
||||||
|
self.base = base
|
||||||
|
|
||||||
|
def save(self, image_id):
|
||||||
|
"""Save thumbnail into specific directory structure
|
||||||
|
return full path to the file and exif object or None"""
|
||||||
|
filepath = os.path.join(self.base, self.__get_and_make_path(image_id))
|
||||||
|
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:
|
||||||
|
t = "/tmp/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')
|
||||||
|
shutil.move(t, filepath)
|
||||||
|
else:
|
||||||
|
f.close()
|
||||||
|
returncode = 0
|
||||||
|
else:
|
||||||
|
im = self.__scale_image(True)
|
||||||
|
if im:
|
||||||
|
im.save(filepath, "JPEG")
|
||||||
|
returncode = 1
|
||||||
|
except:
|
||||||
|
f.close()
|
||||||
|
im = self.__scale_image(True)
|
||||||
|
if im:
|
||||||
|
im.save(filepath, "JPEG")
|
||||||
|
returncode = 2
|
||||||
|
return filepath, exif, returncode
|
||||||
|
|
||||||
|
# private class functions
|
||||||
|
def __get_and_make_path(self, img_id):
|
||||||
|
"""Make directory structure regards of id
|
||||||
|
and return filepath WITHOUT extension"""
|
||||||
|
t = os.path.join(self.base, self.root)
|
||||||
|
try: os.mkdir(t)
|
||||||
|
except: pass
|
||||||
|
h = hex(img_id)
|
||||||
|
if len(h[2:])>6:
|
||||||
|
try: os.mkdir(os.path.join(t, h[2:4]))
|
||||||
|
except: pass
|
||||||
|
try: os.mkdir(os.path.join(t, h[2:4], h[4:6]))
|
||||||
|
except: pass
|
||||||
|
path = os.path.join(t, h[2:4], h[4:6], h[6:8])
|
||||||
|
try: os.mkdir(path)
|
||||||
|
except: pass
|
||||||
|
img = "%s.%s" % (h[8:], 'jpg')
|
||||||
|
elif len(h[2:])>4:
|
||||||
|
try: os.mkdir(os.path.join(t, h[2:4]))
|
||||||
|
except: pass
|
||||||
|
path = os.path.join(t, h[2:4], h[4:6])
|
||||||
|
try: os.mkdir(path)
|
||||||
|
except: pass
|
||||||
|
img = "%s.%s" % (h[6:], 'jpg')
|
||||||
|
elif len(h[2:])>2:
|
||||||
|
path = os.path.join(t, h[2:4])
|
||||||
|
try: os.mkdir(path)
|
||||||
|
except: pass
|
||||||
|
img = "%s.%s" %(h[4:], 'jpg')
|
||||||
|
else:
|
||||||
|
path = t
|
||||||
|
img = "%s.%s" %(h[2:], 'jpg')
|
||||||
|
return(os.path.join(t, img))
|
||||||
|
|
||||||
|
def __scale_image(self, factor=False):
|
||||||
|
"""generate scaled Image object for given file
|
||||||
|
args:
|
||||||
|
factor - if False, adjust height into self.y
|
||||||
|
if True, use self.x for scale portrait pictures height.
|
||||||
|
returns Image object, or False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
im = Image.open(self.filename).convert('RGB')
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
x, y = im.size
|
||||||
|
|
||||||
|
if x > self.x or y > self.y:
|
||||||
|
if x==y:
|
||||||
|
# square
|
||||||
|
imt = im.resize((self.y, self.y), Image.ANTIALIAS)
|
||||||
|
elif x > y:
|
||||||
|
# landscape
|
||||||
|
if int(y/(x/float(self.x))) > self.y:
|
||||||
|
# landscape image: height is non standard
|
||||||
|
self.x1 = int(float(self.y) * self.y / self.x)
|
||||||
|
if float(self.y) * self.y / self.x - self.x1 > 0.49:
|
||||||
|
self.x1 += 1
|
||||||
|
imt = im.resize(((int(x/(y/float(self.y))),self.y)),Image.ANTIALIAS)
|
||||||
|
elif x/self.x==y/self.y:
|
||||||
|
# aspect ratio ok
|
||||||
|
imt = im.resize((self.x, self.y), Image.ANTIALIAS)
|
||||||
|
else:
|
||||||
|
imt = im.resize((self.x,int(y/(x/float(self.x)))), 1)
|
||||||
|
else:
|
||||||
|
# portrait
|
||||||
|
if factor:
|
||||||
|
if y>self.x:
|
||||||
|
imt = im.resize(((int(x/(y/float(self.x))),self.x)),Image.ANTIALIAS)
|
||||||
|
else:
|
||||||
|
imt = im
|
||||||
|
else:
|
||||||
|
self.x1 = int(float(self.y) * self.y / self.x)
|
||||||
|
if float(self.y) * self.y / self.x - self.x1 > 0.49:
|
||||||
|
self.x1 += 1
|
||||||
|
|
||||||
|
if x/self.x1==y/self.y:
|
||||||
|
# aspect ratio ok
|
||||||
|
imt = im.resize((self.x1,self.y),Image.ANTIALIAS)
|
||||||
|
else:
|
||||||
|
imt = im.resize(((int(x/(y/float(self.y))),self.y)),Image.ANTIALIAS)
|
||||||
|
return imt
|
||||||
|
else:
|
||||||
|
return im
|
||||||
|
|
||||||
class Picture(object):
|
class Picture(object):
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
@@ -163,7 +313,39 @@ class MainModel(ModelMT):
|
|||||||
return
|
return
|
||||||
|
|
||||||
os.chdir(self.internal_dirname)
|
os.chdir(self.internal_dirname)
|
||||||
|
try:
|
||||||
tar.extractall()
|
tar.extractall()
|
||||||
|
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()
|
tar.close()
|
||||||
|
|
||||||
self.__connect_to_db()
|
self.__connect_to_db()
|
||||||
@@ -218,9 +400,12 @@ class MainModel(ModelMT):
|
|||||||
self.files_list.set_value(myiter, 6, gtk.STOCK_DIRECTORY)
|
self.files_list.set_value(myiter, 6, gtk.STOCK_DIRECTORY)
|
||||||
|
|
||||||
# all the rest
|
# all the rest
|
||||||
self.db_cursor.execute("SELECT id, filename, size, date, type \
|
self.db_cursor.execute("SELECT f.id, f.filename, f.size, f.date, \
|
||||||
FROM files WHERE parent_id=? AND type!=1 \
|
f.type, f.filetype, t.filename \
|
||||||
ORDER BY filename", (id,))
|
FROM files f \
|
||||||
|
LEFT JOIN thumbnails t ON f.id = t.file_id \
|
||||||
|
WHERE f.parent_id=? AND f.type!=1 \
|
||||||
|
ORDER BY f.filename", (id,))
|
||||||
data = self.db_cursor.fetchall()
|
data = self.db_cursor.fetchall()
|
||||||
for ch in data:
|
for ch in data:
|
||||||
myiter = self.files_list.insert_before(None, None)
|
myiter = self.files_list.insert_before(None, None)
|
||||||
@@ -231,6 +416,9 @@ class MainModel(ModelMT):
|
|||||||
self.files_list.set_value(myiter, 4, ch[4])
|
self.files_list.set_value(myiter, 4, ch[4])
|
||||||
self.files_list.set_value(myiter, 5, 'kategoria srategoria')
|
self.files_list.set_value(myiter, 5, 'kategoria srategoria')
|
||||||
if ch[4] == self.FIL:
|
if ch[4] == self.FIL:
|
||||||
|
if ch[5] == self.F_IMG and ch[6] != None:
|
||||||
|
self.files_list.set_value(myiter, 6, gtk.STOCK_FILE)
|
||||||
|
else:
|
||||||
self.files_list.set_value(myiter, 6, gtk.STOCK_FILE)
|
self.files_list.set_value(myiter, 6, gtk.STOCK_FILE)
|
||||||
elif ch[4] == self.LIN:
|
elif ch[4] == self.LIN:
|
||||||
self.files_list.set_value(myiter, 6, gtk.STOCK_INDEX)
|
self.files_list.set_value(myiter, 6, gtk.STOCK_INDEX)
|
||||||
@@ -372,6 +560,10 @@ class MainModel(ModelMT):
|
|||||||
thumb_x INTEGER,
|
thumb_x INTEGER,
|
||||||
thumb_y INTEGER,
|
thumb_y INTEGER,
|
||||||
thumb_mode TEXT);""")
|
thumb_mode TEXT);""")
|
||||||
|
self.db_cursor.execute("""create table
|
||||||
|
thumbnails(id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
file_id INTEGER,
|
||||||
|
filename TEXT);""")
|
||||||
self.db_cursor.execute("insert into files values(1, 1, 'root', null, \
|
self.db_cursor.execute("insert into files values(1, 1, 'root', null, \
|
||||||
0, 0, 0, 0, null, null, null, null);")
|
0, 0, 0, 0, null, null, null, null);")
|
||||||
|
|
||||||
@@ -388,10 +580,6 @@ class MainModel(ModelMT):
|
|||||||
|
|
||||||
timestamp = datetime.now()
|
timestamp = datetime.now()
|
||||||
|
|
||||||
# TODO: file types has to be moved to configuration model
|
|
||||||
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 files in directory tree
|
||||||
count = 0
|
count = 0
|
||||||
self.statusmsg = "Calculating number of files in directory tree..."
|
self.statusmsg = "Calculating number of files in directory tree..."
|
||||||
@@ -409,6 +597,7 @@ class MainModel(ModelMT):
|
|||||||
step = 1.0/count
|
step = 1.0/count
|
||||||
else:
|
else:
|
||||||
step = 1.0
|
step = 1.0
|
||||||
|
|
||||||
self.count = 0
|
self.count = 0
|
||||||
|
|
||||||
# guess filesystem encoding
|
# guess filesystem encoding
|
||||||
@@ -501,42 +690,15 @@ class MainModel(ModelMT):
|
|||||||
if self.abort:
|
if self.abort:
|
||||||
break
|
break
|
||||||
self.count = self.count + 1
|
self.count = self.count + 1
|
||||||
|
current_path = os.path.join(root,i)
|
||||||
try:
|
try:
|
||||||
st = os.stat(os.path.join(root,i))
|
st = os.stat(current_path)
|
||||||
st_mtime = st.st_mtime
|
st_mtime = st.st_mtime
|
||||||
st_size = st.st_size
|
st_size = st.st_size
|
||||||
except OSError:
|
except OSError:
|
||||||
st_mtime = 0
|
st_mtime = 0
|
||||||
st_size = 0
|
st_size = 0
|
||||||
|
|
||||||
### TODO: scan files
|
|
||||||
if self.config.confd['retrive']:
|
|
||||||
pass
|
|
||||||
#if i.split('.').[-1].lower() in mov_ext:
|
|
||||||
# # video only
|
|
||||||
# info = filetypeHelper.guess_video(os.path.join(root,i))
|
|
||||||
|
|
||||||
|
|
||||||
if i.split('.')[-1].lower() in img_ext:
|
|
||||||
exif_info = EXIF.process_file(open(os.path.join(path,i),
|
|
||||||
'rb'))
|
|
||||||
if exif_info.has_key('JPEGThumbnail'):
|
|
||||||
print "%s got thumbnail" % i
|
|
||||||
else:
|
|
||||||
print "%s has not got thumbnail" % i
|
|
||||||
|
|
||||||
# pass
|
|
||||||
### end of scan
|
|
||||||
|
|
||||||
### progress/status
|
|
||||||
# if wobj.sbid != 0:
|
|
||||||
# wobj.status.remove(wobj.sbSearchCId, wobj.sbid)
|
|
||||||
if self.count % 32 == 0:
|
|
||||||
self.statusmsg = "Scannig: %s" % (os.path.join(root,i))
|
|
||||||
self.progress = step * self.count
|
|
||||||
# # PyGTK FAQ entry 23.20
|
|
||||||
# while gtk.events_pending(): gtk.main_iteration()
|
|
||||||
|
|
||||||
_size = _size + st_size
|
_size = _size + st_size
|
||||||
j = i
|
j = i
|
||||||
if self.fsenc:
|
if self.fsenc:
|
||||||
@@ -549,6 +711,35 @@ class MainModel(ModelMT):
|
|||||||
db_cursor.execute(sql, (currentid, j, os.path.join(path,i),
|
db_cursor.execute(sql, (currentid, j, os.path.join(path,i),
|
||||||
st_mtime, st_size, self.FIL))
|
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
|
||||||
|
sql = """select seq FROM sqlite_sequence WHERE name='files'"""
|
||||||
|
db_cursor.execute(sql)
|
||||||
|
fileid=db_cursor.fetchone()[0]
|
||||||
|
if i.split('.')[-1].lower() in self.config.confd['img_ext']:
|
||||||
|
sql = """UPDATE files set filetype = ? where id = ?"""
|
||||||
|
db_cursor.execute(sql, (self.F_IMG, fileid))
|
||||||
|
if self.config.confd['thumbs']:
|
||||||
|
path, exif, ret_code = Thumbnail(current_path, base=self.internal_dirname).save(fileid)
|
||||||
|
if ret_code != -1:
|
||||||
|
sql = """insert into thumbnails(file_id, filename) values (?, ?)"""
|
||||||
|
db_cursor.execute(sql, (fileid, path.split(self.internal_dirname)[1][1:]))
|
||||||
|
|
||||||
|
#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_path
|
||||||
|
self.progress = step * self.count
|
||||||
|
|
||||||
sql = """update files set size=? where id=?"""
|
sql = """update files set size=? where id=?"""
|
||||||
db_cursor.execute(sql,(_size, currentid))
|
db_cursor.execute(sql,(_size, currentid))
|
||||||
if self.abort:
|
if self.abort:
|
||||||
@@ -628,8 +819,7 @@ class MainModel(ModelMT):
|
|||||||
# launch scanning.
|
# launch scanning.
|
||||||
get_children()
|
get_children()
|
||||||
if __debug__:
|
if __debug__:
|
||||||
print "m_main.py: __fetch_db_into_treestore() tree generation time: ",
|
print "m_main.py: __fetch_db_into_treestore() tree generation time: ", (datetime.now() - start_date)
|
||||||
(datetime.now() - start_date)
|
|
||||||
db_connection.close()
|
db_connection.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -697,8 +887,7 @@ class MainModel(ModelMT):
|
|||||||
# launch scanning.
|
# launch scanning.
|
||||||
get_children()
|
get_children()
|
||||||
if __debug__:
|
if __debug__:
|
||||||
print "m_main.py: __fetch_db_into_treestore() tree generation time: ",
|
print "m_main.py: __fetch_db_into_treestore() tree generation time: ", (datetime.now() - start_date)
|
||||||
(datetime.now() - start_date)
|
|
||||||
db_connection.close()
|
db_connection.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user