diff --git a/README b/README index 1b6030e..ea1f820 100644 --- a/README +++ b/README @@ -56,28 +56,14 @@ For version 1.0 following aims have to be done: - searching database - tagging files -- filetypes handling - - movies - - images - - archives - - documents + - user definied group of tags (represented by color in cloud tag) - file details: - files properties x thumbnail - description - file information (date, size, etc) (50%) - exif information - - keywords - - anime/movie - - title - - alt title - - type (anime movie, movie, anime oav, anime tv series, tv series, etc) - - cover/images - - genre - - lang - - sub lang - - release date (from - to) - - anidb link/imdb link + - keywords (tags) - adding images (60% done) x generating/saving thumbnails x moving hardcoded files extensions into config @@ -90,6 +76,24 @@ For version 2.0: - internationalization support - statistics +Removed: +- filetypes handling (movies, images, archives, documents etc). Now it have + common, unified external "plugin" system - simple output from command line + programs. +- anime/movie + - title + - alt title + - type (anime movie, movie, anime oav, anime tv series, tv series, etc) + - cover/images + - genre + - lang + - sub lang + - release date (from - to) + - anidb link/imdb link + Maybe in future versions. Now text file descriptions and tags have to be + enough for good and fast information search. + + NOTES ===== diff --git a/resources/glade/config.glade b/resources/glade/config.glade index 50ece8f..c08eadd 100644 --- a/resources/glade/config.glade +++ b/resources/glade/config.glade @@ -89,16 +89,57 @@ 3 3 - + True 0 - Eject program: - ejt_entry + Mount point: + mnt_entry + + + + + + + 100 + True + True + + + 1 + 2 + + + + + + True + True + Browse... + True + 0 + + + + + 2 + 3 + + + + + + + 100 + True + True + + + 1 + 2 1 2 - @@ -122,56 +163,15 @@ - - 100 - True - True - - - 1 - 2 - 1 - 2 - - - - - - True - True - Browse... - True - 0 - - - - - 2 - 3 - - - - - - - 100 - True - True - - - 1 - 2 - - - - - + True 0 - Mount point: - mnt_entry + Eject program: + ejt_entry + 1 + 2 @@ -532,25 +532,11 @@ True 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Images extensions -Movies extesions - - - - False - False - 3 - - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 + 2 2 3 @@ -576,10 +562,33 @@ Movies extesions GTK_FILL + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Command: + + + 1 + 2 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 1 + 2 + 1 + 2 + + False - 1 @@ -594,7 +603,7 @@ Movies extesions True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Add + Add/Change 0 @@ -616,7 +625,7 @@ Movies extesions False - 2 + 1 @@ -633,11 +642,12 @@ Movies extesions True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True + - 3 + 2 @@ -661,300 +671,6 @@ Movies extesions 3 - - - 1 - - - True - 5 - 0 - - - True - True - 5 - 12 - - - True - 5 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 2 - 3 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Command: - GTK_JUSTIFY_RIGHT - ext_entry - - - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - GTK_BUTTONBOX_END - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Add - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Delete - 0 - - - 1 - - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 0 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 3 - 2 - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-forward - True - GTK_POS_TOP - 0 - - - False - False - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-go-back - True - 0 - - - False - False - 1 - - - - - 1 - 2 - 1 - 2 - GTK_SHRINK - GTK_SHRINK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Command extensions - - - GTK_SHRINK - GTK_SHRINK - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Available extensions - - - 2 - 3 - GTK_SHRINK - GTK_SHRINK - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - GTK_POLICY_AUTOMATIC - GTK_POLICY_AUTOMATIC - GTK_SHADOW_IN - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - 2 - 3 - 1 - 2 - - - - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Extension assignment</b> - True - - - label_item - - - - - 1 - - - - - 2 - - - - - - - - - True - <b>Comands</b> - True - - - label_item - - - - - - - 4 - - diff --git a/resources/glade/main.glade b/resources/glade/main.glade index f09c6a3..3f3029c 100644 --- a/resources/glade/main.glade +++ b/resources/glade/main.glade @@ -652,6 +652,8 @@ GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False GTK_WRAP_WORD + 2 + 2 False @@ -866,4 +868,24 @@ + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + _Add tag + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + Add _thumbnail + True + + + diff --git a/src/ctrls/c_config.py b/src/ctrls/c_config.py index 2b44fa2..a30e7ba 100644 --- a/src/ctrls/c_config.py +++ b/src/ctrls/c_config.py @@ -32,10 +32,9 @@ class ConfigController(Controller): 'General':'general_group', 'Scan options':'scan_group', 'Files extensions':'ft_group', - 'Commands':'commands_group', } category_order = ['General', 'Disk options', 'Scan options', - 'Files extensions', 'Commands'] + 'Files extensions',] def __init__(self, model): Controller.__init__(self, model) @@ -67,15 +66,23 @@ class ConfigController(Controller): self.__setup_category_tree() # initialize models for files extensions - self.view['ext_choose'].set_model(self.model.ext_list) - self.view['ext_choose'].set_active(0) self.view['extension_tree'].get_selection().set_mode(gtk.SELECTION_MULTIPLE) + #self.view['extension_tree'].set_model(self.model.ext_tree) + self.__setup_extension_tree() + self.view['config'].show(); return # Podłącz sygnały: ################# # connect signals + def on_extension_tree_cursor_changed(self, tree): + model = tree.get_model() + selected = model.get_value(model.get_iter(tree.get_cursor()[0]), 0) + ext = self.model.confd['extensions'] + self.view['ext_entry'].set_text(selected) + self.view['com_entry'].set_text(ext[selected]) + def on_category_tree_cursor_changed(self, tree): """change view to selected row corresponding to group of properties""" model = tree.get_model() @@ -127,22 +134,28 @@ class ConfigController(Controller): self.__toggle_scan_group() return - 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() + com = self.view['com_entry'].get_text() + if len(ext) == 0 and len(com) == 0: + Dialogs.Err("Config - pyGTKtalog", "Error", "Extension and command required") + return + + if len(com) == 0: + Dialogs.Err("Config - pyGTKtalog", "Error", "Command is empty") + return + 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) + + if ext in self.model.confd['extensions'].keys(): + obj = Dialogs.Qst('Alter extension', + 'Alter extension?', + 'Extension "%s" will be altered.' % ext) + if not obj.run(): + return + self.model.confd['extensions'][ext] = com self.__setup_extension_tree() return @@ -164,13 +177,8 @@ class ConfigController(Controller): 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.model.confd['extensions'].pop(model.get_value(model.get_iter(i), 0)) self.__setup_extension_tree() return @@ -178,17 +186,18 @@ class ConfigController(Controller): ############################ # private controller methods def __setup_extension_tree(self): - if self.view['ext_choose'].get_active() == 0: - self.model.refresh_ext('img_ext') - else: - self.model.refresh_ext('mov_ext') + self.model.refresh_ext() self.view['extension_tree'].set_model(self.model.ext_tree) for i in self.view['extension_tree'].get_columns(): self.view['extension_tree'].remove_column(i) cell = gtk.CellRendererText() - column = gtk.TreeViewColumn("Extensions", cell, text=0) + column = gtk.TreeViewColumn("Extension", cell, text=0) + column.set_resizable(True) + self.view['extension_tree'].append_column(column) + + column = gtk.TreeViewColumn("Command", cell, text=1) column.set_resizable(True) self.view['extension_tree'].append_column(column) @@ -196,6 +205,7 @@ class ConfigController(Controller): for i in ('ch_thumb','ch_exif','ch_gthumb'): self.view[i].set_sensitive(self.view['ch_retrive'].get_active()) return + def __setup_category_tree(self): category_tree = self.view['category_tree'] category_tree.set_model(self.model.category_tree) diff --git a/src/ctrls/c_main.py b/src/ctrls/c_main.py index b170d9d..2baa4fe 100644 --- a/src/ctrls/c_main.py +++ b/src/ctrls/c_main.py @@ -40,6 +40,7 @@ from models.m_config import ConfigModel import views.v_dialogs as Dialogs import gtk +import pango import datetime @@ -288,24 +289,23 @@ class MainController(Controller): def on_files_cursor_changed(self,treeview): """Show details of selected file""" model, paths = treeview.get_selection().get_selected_rows() - try: - itera = model.get_iter(paths[0]) - if model.get_value(itera,4) == 1: - #directory, do nothin', just turn off view - '''self.view['details'].hide() - buf = self.view['details'].get_buffer() - buf.set_text('') - self.view['details'].set_buffer(buf)''' - else: - #file, show what you got. - #self.details.get_top_widget() - iter = model.get_iter(treeview.get_cursor()[0]) - 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" + #try: + itera = model.get_iter(paths[0]) + if model.get_value(itera,4) == 1: + #directory, do nothin', just turn off view + '''self.view['details'].hide() + buf = self.view['details'].get_buffer() + buf.set_text('') + self.view['details'].set_buffer(buf)''' + else: + #file, show what you got. + #self.details.get_top_widget() + iter = model.get_iter(treeview.get_cursor()[0]) + 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" return def on_files_key_release_event(self, a, event): @@ -554,8 +554,7 @@ class MainController(Controller): self.model.config.confd['confirmquit']: if not Dialogs.Qst('Quit application - pyGTKtalog', 'Do you really want to quit?', - "Current database is not saved, any changes \ - will be lost.").run(): + "Current database is not saved, any changes will be lost.").run(): return self.__store_settings() @@ -571,16 +570,15 @@ class MainController(Controller): if self.model.unsaved_project: if not Dialogs.Qst('Unsaved data - pyGTKtalog', "Current database isn't saved", - 'All changes will be lost. \ - Do you really want to abandon it?').run(): + 'All changes will be lost. Do you really want to abandon it?').run(): return self.model.new() # clear "details" buffer - '''txt = "" - buf = self.view['details'].get_buffer() - buf.set_text(txt) - self.view['details'].set_buffer(buf)''' + buf = self.view['description'].get_buffer() + buf.set_text("") + self.view['description'].set_buffer(buf) + self.view['thumb'].hide() self.__activate_ui() @@ -729,10 +727,16 @@ 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() - if set.has_key('description'): - buf.set_text(set['description']) + + 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('') self.view['description'].set_buffer(buf) diff --git a/src/models/m_config.py b/src/models/m_config.py index f5b859c..8a198c7 100644 --- a/src/models/m_config.py +++ b/src/models/m_config.py @@ -75,7 +75,7 @@ class ConfigModel(Model): 'mntwarn': True, 'delwarn': True, - 'cd': '/cdrom', + 'cd': '/mnt/cdrom', 'ejectapp': 'eject -r', 'retrive': False, @@ -84,8 +84,17 @@ class ConfigModel(Model): 'exif': True, 'gthumb': False, - 'mov_ext': ['avi', 'mkv', 'mpg', 'mpeg', 'wmv'], - 'img_ext': ['bmp', 'gif', 'jpg', 'jpeg', 'png'], + 'extensions': {'bmp':'identify %s', + 'gif':'identify "%s"', + 'jpg':'identify "%s"', + 'jpeg':'identify "%s"', + 'png':'identify "%s"', + 'avi':'midentify "%s"', + 'mkv':'midentify "%s"', + 'mpg':'midentify "%s"', + 'mpeg':'midentify "%s"', + 'wmv':'midentify "%s"', + }, 'showtoolbar':True, 'showstatusbar':True, @@ -147,21 +156,19 @@ class ConfigModel(Model): def __init__(self): Model.__init__(self) self.category_tree = gtk.ListStore(gobject.TYPE_STRING) - self.ext_list = gtk.ListStore(gobject.TYPE_STRING) - for i in self.filetype_list: - myiter = self.ext_list.insert_before(None,None) - self.ext_list.set_value(myiter,0,i) - - self.refresh_ext('img_ext') + + self.refresh_ext() return - def refresh_ext(self, key): - self.ext_tree = gtk.ListStore(gobject.TYPE_STRING) - self.confd[key].sort() - for i in self.confd[key]: + def refresh_ext(self): + self.ext_tree = gtk.ListStore(gobject.TYPE_STRING, + gobject.TYPE_STRING) + keys = sorted(self.confd['extensions'].keys()) + for i in keys: myiter = self.ext_tree.insert_before(None,None) - self.ext_tree.set_value(myiter,0,i) + self.ext_tree.set_value(myiter, 0, i) + self.ext_tree.set_value(myiter, 1, self.confd['extensions'][i]) def save(self): try: @@ -190,16 +197,10 @@ class ConfigModel(Model): count+=1 # extensions sections - newIni.add_section("images extensions") + newIni.add_section("extensions") count = 1 - for i in self.confd['img_ext']: - newIni.add_key(count, i) - count+=1 - - newIni.add_section("movies extensions") - count = 1 - for i in self.confd['mov_ext']: - newIni.add_key(count, i) + for i in self.confd['extensions']: + newIni.add_key(i, self.confd['extensions'][i]) count+=1 # write config @@ -243,26 +244,16 @@ class ConfigModel(Model): if __debug__: print "m_config.py: load() failed to parse option:", opt pass - elif sec == 'images extensions': - self.confd['img_ext'] = [] + elif sec == 'extensions': + self.confd['extensions'] = {} for opt in parser.options(sec): try: - self.confd['img_ext'].append(parser.get(sec,opt)) + self.confd['extensions'][opt] = parser.get(sec, opt) except: if __debug__: print "m_config.py: load() failed to parse option:", opt pass - elif sec == 'movies extensions': - self.confd['mov_ext'] = [] - for opt in parser.options(sec): - try: - self.confd['mov_ext'].append(parser.get(sec,opt)) - except: - if __debug__: - print "m_config.py: load() failed to parse option:", opt - pass - for i in range(1, self.RECENT_MAX + 1): if r.has_key(i): self.recent.append(r[i]) diff --git a/src/models/m_main.py b/src/models/m_main.py index 493692f..c40550f 100644 --- a/src/models/m_main.py +++ b/src/models/m_main.py @@ -28,6 +28,7 @@ import base64 import shutil import tarfile import tempfile +import string import gtk import gobject @@ -58,17 +59,13 @@ class MainModel(ModelMT): FIL = 2 # file LIN = 3 # symbolic link - # filetype kind of - F_UNK = 0 # unknown - default - F_IMG = 1 # images - jpg, gif, tiff itd - F_MOV = 2 # movies and clips - mpg, ogm, mkv, avi, asf, wmv itd - F_MUS = 4 # music - flac, mp3, mpc, ogg itd - F_APP = 5 # applications - F_DOC = 6 # all kind of documents txt/pdf/doc/odf itd - CD = 1 # sorce: cd/dvd DR = 2 # source: filesystem + # 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() @@ -255,9 +252,7 @@ class MainModel(ModelMT): # all the rest self.db_cursor.execute("SELECT f.id, f.filename, f.size, f.date, \ - f.type, f.filetype, t.filename \ - FROM files f \ - LEFT JOIN thumbnails t ON f.id = t.file_id \ + f.type FROM files f \ WHERE f.parent_id=? AND f.type!=1 \ ORDER BY f.filename", (id,)) data = self.db_cursor.fetchall() @@ -270,14 +265,11 @@ class MainModel(ModelMT): self.files_list.set_value(myiter, 4, ch[4]) self.files_list.set_value(myiter, 5, 'kategoria srategoria') if ch[4] == self.FIL: - if ch[6] != None: - # TODO: change icon to thumbnail - 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: 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,)) @@ -290,7 +282,7 @@ class MainModel(ModelMT): """get file info from database""" retval = {} self.db_cursor.execute("SELECT f.filename, f.date, f.size, f.type, \ - t.filename \ + t.filename, f.description \ FROM files f \ LEFT JOIN thumbnails t ON t.file_id = f.id \ WHERE f.id = ?", (id,)) @@ -298,7 +290,9 @@ class MainModel(ModelMT): 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['description'] = string + retval['file_info'] = string + if set[5]: + retval['description'] = set[5] if set[4]: retval['thumbnail'] = os.path.join(self.internal_dirname, set[4]) @@ -408,22 +402,11 @@ class MainModel(ModelMT): size_x integer, size_y integer, filetype integer, - note TEXT);""") + description TEXT);""") self.db_cursor.execute("""create table tags(id INTEGER PRIMARY KEY AUTOINCREMENT, file_id INTEGER, tag TEXT);""") - self.db_cursor.execute("""create table - descriptions(id INTEGER PRIMARY KEY AUTOINCREMENT, - file_id INTEGER, - desc TEXT, - image TEXT, - image_x INTEGER, - image_y INTEGER, - thumb TEXT, - thumb_x INTEGER, - thumb_y INTEGER, - thumb_mode TEXT);""") self.db_cursor.execute("""create table thumbnails(id INTEGER PRIMARY KEY AUTOINCREMENT, file_id INTEGER, @@ -586,16 +569,34 @@ class MainModel(ModelMT): 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:])) + 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: + 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 self.config.confd['exif']: + # TODO: exif implementation + pass + + # Extensions - user defined actions + if ext in self.config.confd['extensions'].keys(): + cmd = self.config.confd['extensions'][ext] + arg = string.replace(current_path, '"', '\\"') + 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)) diff --git a/src/utils/thumbnail.py b/src/utils/thumbnail.py index b7e58d4..1c2ba92 100644 --- a/src/utils/thumbnail.py +++ b/src/utils/thumbnail.py @@ -56,6 +56,7 @@ class Thumbnail(object): 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