1
0
mirror of https://github.com/gryf/pygtktalog.git synced 2025-12-17 19:40:21 +01:00

* Added support for "menu" key on keyboard.

* Small changes in behaviour of individual popup menus.
This commit is contained in:
2008-05-06 19:17:10 +00:00
parent aea871b30e
commit 33b5e76f99
6 changed files with 328 additions and 192 deletions

21
README
View File

@@ -1,4 +1,4 @@
pyGTKtalog 0.8 pyGTKtalog 0.9
============== ==============
pyGTKtalog Linux/FreeBSD program for indexing CD/DVD or directories on pyGTKtalog Linux/FreeBSD program for indexing CD/DVD or directories on
@@ -24,6 +24,7 @@ REQUIREMENTS
pyGTKtalog is written in python with following dependencies: pyGTKtalog is written in python with following dependencies:
- python 2.4 or higher
- pygtk <http://www.pygtk.org> - pygtk <http://www.pygtk.org>
- pysqlite2 <http://pysqlite.org/> (unnecessary, if python 2.5 is used) - pysqlite2 <http://pysqlite.org/> (unnecessary, if python 2.5 is used)
@@ -37,7 +38,7 @@ Additional pyGTKtalog uses EXIF module by Gene Cash which is included in
sources. sources.
pyGTKtalog extensivly uses external programs in unix spirit, however there is pyGTKtalog extensivly uses external programs in unix spirit, however there is
small possibility of using it Windows (probably with liitations) and quite big small possibility of using it Windows (probably with limitations) and quite big
possiblity to run it on other sofisticated unix-like systems (i.e. possiblity to run it on other sofisticated unix-like systems (i.e.
BeOS/ZETA/Haiku, QNX or MacOSX). BeOS/ZETA/Haiku, QNX or MacOSX).
@@ -57,11 +58,14 @@ Then, just run pyGTKtalog script.
TODO TODO
==== ====
For version 1.0 following aims have to be done: PyGTKtalog is still under heavy development, however there is small chance to
change structure of catalogs (and if it'll change, there will be transparent
function to update DB schema).
For version 1.0 following major aims have to be done:
- searching database - searching database
- tagging files (90%) x tagging files
- user definied group of tags (represented by color in cloud tag)
x remove nasty bug in redraw of tag cloud x remove nasty bug in redraw of tag cloud
x file details: x file details:
x files properties x files properties
@@ -75,6 +79,10 @@ x generating/saving thumbnails
x moving hardcoded files extensions into config x moving hardcoded files extensions into config
x statistics x statistics
There are still minor aims for versions 1.x to be done:
- consolidate popup-menus with edit menu
- add popup menu for directly removing tag from tag cloud
Legend: [-] not done, [x] done. Legend: [-] not done, [x] done.
For version 2.0: For version 2.0:
@@ -82,6 +90,9 @@ For version 2.0:
- command line support: query, adding media to collection etc - command line support: query, adding media to collection etc
- internationalization support - internationalization support
- export to XLS - export to XLS
- user definied group of tags (represented by color in cloud tag)
- hiding specified files - configurable, like dot prefixed, cfg and manualy
selected
Removed: Removed:
- filetypes handling (movies, images, archives, documents etc). Now it have - filetypes handling (movies, images, archives, documents etc). Now it have

View File

@@ -93,35 +93,9 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">_Edit</property> <property name="label" translatable="yes">_Edit</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_edit1_activate"/>
<child> <child>
<widget class="GtkMenu" id="edit1_menu"> <widget class="GtkMenu" id="edit1_menu">
<child>
<widget class="GtkImageMenuItem" id="cut1">
<property name="visible">True</property>
<property name="label">gtk-cut</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_cut1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="copy1">
<property name="visible">True</property>
<property name="label">gtk-copy</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_copy1_activate"/>
</widget>
</child>
<child>
<widget class="GtkImageMenuItem" id="paste1">
<property name="visible">True</property>
<property name="label">gtk-paste</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="on_paste1_activate"/>
</widget>
</child>
<child> <child>
<widget class="GtkImageMenuItem" id="delete1"> <widget class="GtkImageMenuItem" id="delete1">
<property name="visible">True</property> <property name="visible">True</property>
@@ -129,6 +103,7 @@
<property name="use_underline">True</property> <property name="use_underline">True</property>
<property name="use_stock">True</property> <property name="use_stock">True</property>
<signal name="activate" handler="on_delete1_activate"/> <signal name="activate" handler="on_delete1_activate"/>
<accelerator key="Delete" modifiers="" signal="activate"/>
</widget> </widget>
</child> </child>
<child> <child>
@@ -177,7 +152,7 @@
<property name="label" translatable="yes">Add _CD/DVD</property> <property name="label" translatable="yes">Add _CD/DVD</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_add_cd_activate"/> <signal name="activate" handler="on_add_cd_activate"/>
<accelerator key="a" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="c" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget> </widget>
</child> </child>
<child> <child>
@@ -185,7 +160,7 @@
<property name="visible">True</property> <property name="visible">True</property>
<property name="label" translatable="yes">Add _Directory</property> <property name="label" translatable="yes">Add _Directory</property>
<property name="use_underline">True</property> <property name="use_underline">True</property>
<signal name="activate" handler="on_add_directory1_activate"/> <signal name="activate" handler="on_add_directory_activate"/>
<accelerator key="d" modifiers="GDK_CONTROL_MASK" signal="activate"/> <accelerator key="d" modifiers="GDK_CONTROL_MASK" signal="activate"/>
</widget> </widget>
</child> </child>
@@ -371,6 +346,18 @@
<property name="expand">False</property> <property name="expand">False</property>
</packing> </packing>
</child> </child>
<child>
<widget class="GtkToolButton" id="tb_adddir">
<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">Add Dir</property>
<property name="stock_id">gtk-directory</property>
<signal name="clicked" handler="on_add_directory_activate"/>
</widget>
<packing>
<property name="expand">False</property>
</packing>
</child>
<child> <child>
<widget class="GtkToolButton" id="tb_find"> <widget class="GtkToolButton" id="tb_find">
<property name="visible">True</property> <property name="visible">True</property>
@@ -501,6 +488,7 @@
<signal name="button_press_event" handler="on_discs_button_press_event"/> <signal name="button_press_event" handler="on_discs_button_press_event"/>
<signal name="row_activated" handler="on_discs_row_activated"/> <signal name="row_activated" handler="on_discs_row_activated"/>
<signal name="cursor_changed" handler="on_discs_cursor_changed"/> <signal name="cursor_changed" handler="on_discs_cursor_changed"/>
<signal name="key_release_event" handler="on_discs_key_release_event"/>
</widget> </widget>
</child> </child>
</widget> </widget>
@@ -672,6 +660,7 @@
<property name="tooltip" translatable="yes">Double click to open image</property> <property name="tooltip" translatable="yes">Double click to open image</property>
<signal name="button_press_event" handler="on_images_button_press_event"/> <signal name="button_press_event" handler="on_images_button_press_event"/>
<signal name="item_activated" handler="on_images_item_activated"/> <signal name="item_activated" handler="on_images_item_activated"/>
<signal name="key_release_event" handler="on_images_key_release_event"/>
</widget> </widget>
</child> </child>
</widget> </widget>
@@ -1025,4 +1014,17 @@
</widget> </widget>
</child> </child>
</widget> </widget>
<widget class="GtkMenu" id="tag_popup">
<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>
<child>
<widget class="GtkMenuItem" id="delete_tag2">
<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">Delete tag</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_delete_tag2_activate"/>
</widget>
</child>
</widget>
</glade-interface> </glade-interface>

View File

@@ -47,9 +47,9 @@ import pango
class MainController(Controller): class MainController(Controller):
"""Controller for main application window""" """Controller for main application window"""
scan_cd = False scan_cd = False
widgets = ("discs", "files", 'save1', 'save_as1', 'cut1', 'copy1', widgets = ("discs", "files", 'save1', 'save_as1', 'delete1', 'add_cd',
'paste1', 'delete1', 'add_cd', 'add_directory1', 'tb_save', 'add_directory1', 'tb_save', 'tb_addcd', 'tb_find', 'nb_dirs',
'tb_addcd', 'tb_find', 'nb_dirs', 'description', 'stat1') 'description', 'stat1')
widgets_all = ("discs", "files", 'file1', 'edit1', 'add_cd', widgets_all = ("discs", "files", 'file1', 'edit1', 'add_cd',
'add_directory1', 'help1', 'tb_save', 'tb_addcd', 'tb_find', 'add_directory1', 'help1', 'tb_save', 'tb_addcd', 'tb_find',
'tb_new', 'tb_open', 'tb_quit', 'nb_dirs', 'description', 'tb_new', 'tb_open', 'tb_quit', 'nb_dirs', 'description',
@@ -72,7 +72,7 @@ class MainController(Controller):
for widget in self.widgets: for widget in self.widgets:
self.view[widget].set_sensitive(False) self.view[widget].set_sensitive(False)
# Make not active "Cancel" button and menuitem # Make not active "Cancel" button and menu_item
for widget in self.widgets_cancel: for widget in self.widgets_cancel:
self.view[widget].set_sensitive(False) self.view[widget].set_sensitive(False)
@@ -124,6 +124,9 @@ class MainController(Controller):
# generate recent menu # generate recent menu
self.__generate_recent_menu() self.__generate_recent_menu()
self.view['tag_cloud_textview'].connect("populate-popup",
self.on_tag_cloud_textview_popup)
# in case model has opened file, register tags # in case model has opened file, register tags
if self.model.internal_dirname: if self.model.internal_dirname:
self.__tag_cloud() self.__tag_cloud()
@@ -173,6 +176,10 @@ class MainController(Controller):
string = str(tuple(ids)).replace(",)", ")") string = str(tuple(ids)).replace(",)", ")")
selection.set(selection.target, 8, string) selection.set(selection.target, 8, string)
def on_tag_cloud_textview_popup(self, textview, menu):
menu = None
return True
def on_tag_cloud_textview_event_after(self, textview, event): def on_tag_cloud_textview_event_after(self, textview, event):
if event.type != gtk.gdk.BUTTON_RELEASE: if event.type != gtk.gdk.BUTTON_RELEASE:
return False return False
@@ -220,7 +227,7 @@ class MainController(Controller):
def on_tag_cloud_textview_drag_data_received(self, widget, context, x, y, def on_tag_cloud_textview_drag_data_received(self, widget, context, x, y,
selection, targetType, time): selection, targetType, time):
"""recive data from source TV""" """recive data from source TreeView"""
if targetType == self.DND_TARGETS[0][2]: if targetType == self.DND_TARGETS[0][2]:
iter = widget.get_iter_at_location(x, y) iter = widget.get_iter_at_location(x, y)
ids = selection.data.rstrip(")").lstrip("(").split(",") ids = selection.data.rstrip(")").lstrip("(").split(",")
@@ -556,7 +563,7 @@ class MainController(Controller):
"Last mount message:\n%s" % mount) "Last mount message:\n%s" % mount)
return False return False
def on_add_directory1_activate(self, widget, path=None, label=None, def on_add_directory_activate(self, widget, path=None, label=None,
current_id=None): current_id=None):
"""Show dialog for choose drectory to add from filesystem.""" """Show dialog for choose drectory to add from filesystem."""
if not label or not path: if not label or not path:
@@ -694,30 +701,53 @@ class MainController(Controller):
treeview.expand_row(path, False) treeview.expand_row(path, False)
return return
def on_images_button_press_event(self, iconview, event): def on_discs_key_release_event(self, treeview, event):
try: if gtk.gdk.keyval_name(event.keyval) == 'Menu':
path_and_cell = iconview.get_item_at_pos(int(event.x), ids = self.__get_tv_selection_ids(treeview)
int(event.y)) menu_items = ['update1','rename1','delete2', 'statistics1']
except TypeError: for menu_item in menu_items:
self.view[menu_item].set_sensitive(not not ids)
self.__popup_menu(event, 'discs_popup')
return True
return False return False
if event.button == 3: # Right mouse button. Show context menu. def on_images_key_release_event(self, iconview, event):
try: if gtk.gdk.keyval_name(event.keyval) == 'Menu':
iconview.select_path(path_and_cell[0]) self.__popup_menu(event, 'img_popup')
except TypeError: return True
return False return False
def on_images_button_press_event(self, iconview, event):
#try:
# path_and_cell = iconview.get_item_at_pos(int(event.x),
# int(event.y))
#except TypeError:
# return False
if event.button == 3: # Right mouse button. Show context menu.
#try:
# iconview.select_path(path_and_cell[0])
#except TypeError:
# return False
self.__popup_menu(event, 'img_popup') self.__popup_menu(event, 'img_popup')
return True return True
return False return False
def on_img_delete_activate(self, menu_item): def on_img_delete_activate(self, menu_item):
"""delete selected images (with thumbnails)"""
list_of_paths = self.view['images'].get_selected_items()
if not list_of_paths:
Dialogs.Inf("Delete images", "No images selected",
"You have to select at least one image to delete.")
return
if self.model.config.confd['delwarn']: if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete images', 'Delete selected images?', obj = Dialogs.Qst('Delete images', 'Delete selected images?',
'Selected images will be permanently removed from catalog.') 'Selected images will be permanently removed from catalog.')
if not obj.run(): if not obj.run():
return return
list_of_paths = self.view['images'].get_selected_items()
model = self.view['images'].get_model() model = self.view['images'].get_model()
for path in list_of_paths: for path in list_of_paths:
iter = model.get_iter(path) iter = model.get_iter(path)
@@ -751,12 +781,19 @@ class MainController(Controller):
count = 0 count = 0
if len(list_of_paths) == 0:
# no picture was selected. default to save all of them
for image in model:
if self.model.save_image(image[0], filepath):
count += 1
else:
# some pictures was selected, save them
for path in list_of_paths: for path in list_of_paths:
icon_iter = model.get_iter(path) icon_iter = model.get_iter(path)
img_id = model.get_value(icon_iter, 0) img_id = model.get_value(icon_iter, 0)
if self.model.save_image(img_id, filepath): if self.model.save_image(img_id, filepath):
count += 1 count += 1
if len(list_of_paths) > 0:
if count > 0: if count > 0:
Dialogs.Inf("Save images", Dialogs.Inf("Save images",
"%d images was succsefully saved." % count, "%d images was succsefully saved." % count,
@@ -766,9 +803,17 @@ class MainController(Controller):
"No images was saved.", "No images was saved.",
"Images probably don't have real images - only" + \ "Images probably don't have real images - only" + \
" thumbnails.") " thumbnails.")
return
def on_img_delete2_activate(self, menu_item): def on_img_delete2_activate(self, menu_item):
"""remove images, but keep thumbnails""" """remove images, but keep thumbnails"""
list_of_paths = self.view['images'].get_selected_items()
if not list_of_paths:
Dialogs.Inf("Delete images", "No images selected",
"You have to select at least one image to delete.")
return
if self.model.config.confd['delwarn']: if self.model.config.confd['delwarn']:
obj = Dialogs.Qst('Delete images', 'Delete selected images?', obj = Dialogs.Qst('Delete images', 'Delete selected images?',
'Selected images will be permanently removed from ' + \ 'Selected images will be permanently removed from ' + \
@@ -776,7 +821,6 @@ class MainController(Controller):
if not obj.run(): if not obj.run():
return return
list_of_paths = self.view['images'].get_selected_items()
model = self.view['images'].get_model() model = self.view['images'].get_model()
for path in list_of_paths: for path in list_of_paths:
iter = model.get_iter(path) iter = model.get_iter(path)
@@ -822,31 +866,29 @@ class MainController(Controller):
if path not in list_of_paths: if path not in list_of_paths:
treeview.get_selection().unselect_all() treeview.get_selection().unselect_all()
treeview.get_selection().select_path(path) treeview.get_selection().select_path(path)
# setup menu
ids = self.__get_tv_selection_ids(treeview)
menu_items = ['update1','rename1','delete2', 'statistics1']
for menu_item in menu_items:
self.view[menu_item].set_sensitive(not not ids)
iter = self.model.discs_tree.get_iter(path) # checkout, if we dealing with disc or directory
if self.model.discs_tree.get_value(iter, 3) == 1:
# if ancestor is 'root', then activate "update" menu item # if ancestor is 'root', then activate "update" menu item
self.view['update1'].set_sensitive(True) treeiter = self.model.discs_tree.get_iter(path)
else: ancestor = self.model.discs_tree.get_value(treeiter, 3) == 1
self.view['update1'].set_sensitive(False) self.view['update1'].set_sensitive(ancestor)
self.__popup_menu(event) self.__popup_menu(event)
def on_expand_all1_activate(self, menuitem): def on_expand_all1_activate(self, menu_item):
self.view['discs'].expand_all() self.view['discs'].expand_all()
return return
def on_collapse_all1_activate(self, menuitem): def on_collapse_all1_activate(self, menu_item):
self.view['discs'].collapse_all() self.view['discs'].collapse_all()
return return
def on_files_button_press_event(self, tree, event): def on_files_button_press_event(self, tree, event):
try:
path, column, x, y = tree.get_path_at_pos(int(event.x),
int(event.y))
except TypeError:
tree.get_selection().unselect_all()
return False
if event.button == 3: # Right mouse button. Show context menu. if event.button == 3: # Right mouse button. Show context menu.
try: try:
selection = tree.get_selection() selection = tree.get_selection()
@@ -855,6 +897,14 @@ class MainController(Controller):
list_of_paths = [] list_of_paths = []
if len(list_of_paths) == 0: if len(list_of_paths) == 0:
# try to select item under cursor
try:
path, column, x, y = tree.get_path_at_pos(int(event.x),
int(event.y))
except TypeError:
# failed, do not show any popup and return
tree.get_selection().unselect_all()
return False
selection.select_path(path[0]) selection.select_path(path[0])
if len(list_of_paths) > 1: if len(list_of_paths) > 1:
@@ -867,8 +917,8 @@ class MainController(Controller):
self.view['edit2'].set_sensitive(True) self.view['edit2'].set_sensitive(True)
self.__popup_menu(event, 'files_popup') self.__popup_menu(event, 'files_popup')
return True return True
if event.button == 1: #if event.button == 1:
return False # return False
def on_files_cursor_changed(self, treeview): def on_files_cursor_changed(self, treeview):
"""Show details of selected file/directory""" """Show details of selected file/directory"""
@@ -877,6 +927,17 @@ class MainController(Controller):
return return
def on_files_key_release_event(self, treeview, event): def on_files_key_release_event(self, treeview, event):
"""do something with pressed keys"""
if gtk.gdk.keyval_name(event.keyval) == 'Menu':
try:
selection = treeview.get_selection()
model, list_of_paths = selection.get_selected_rows()
if not list_of_paths:
return
except TypeError:
return
self.__popup_menu(event, 'files_popup')
if gtk.gdk.keyval_name(event.keyval) == 'BackSpace': if gtk.gdk.keyval_name(event.keyval) == 'BackSpace':
d_path, d_column = self.view['discs'].get_cursor() d_path, d_column = self.view['discs'].get_cursor()
if d_path and d_column: if d_path and d_column:
@@ -903,9 +964,9 @@ class MainController(Controller):
iter = None iter = None
else: else:
iter = self.model.discs_tree.iter_next(iter) iter = self.model.discs_tree.iter_next(iter)
if gtk.gdk.keyval_name(event.keyval) == 'Delete': #if gtk.gdk.keyval_name(event.keyval) == 'Delete':
for file_id in self.__get_tv_selection_ids(treeview): # for file_id in self.__get_tv_selection_ids(treeview):
self.main.delete(file_id) # self.main.delete(file_id)
ids = self.__get_tv_selection_ids(self.view['files']) ids = self.__get_tv_selection_ids(self.view['files'])
@@ -951,6 +1012,9 @@ class MainController(Controller):
return return
# NOTE: add tags / images # NOTE: add tags / images
def on_delete_tag2_activate(self, menu_item):
pass
def on_delete_tag_activate(self, menu_item): def on_delete_tag_activate(self, menu_item):
ids = self.__get_tv_selection_ids(self.view['files']) ids = self.__get_tv_selection_ids(self.view['files'])
if not ids: if not ids:
@@ -996,8 +1060,8 @@ class MainController(Controller):
def on_add_image1_activate(self, menu_item): def on_add_image1_activate(self, menu_item):
dialog = Dialogs.LoadImageFile(True) dialog = Dialogs.LoadImageFile(True)
toggle = gtk.CheckButton("Don't copy images. \ toggle = gtk.CheckButton("Don't copy images. " + \
Generate only thumbnails.") "Generate only thumbnails.")
toggle.show() toggle.show()
dialog.dialog.set_extra_widget(toggle) dialog.dialog.set_extra_widget(toggle)
@@ -1039,10 +1103,19 @@ class MainController(Controller):
if self.model.get_source(path) == self.model.CD: if self.model.get_source(path) == self.model.CD:
self.on_add_cd_activate(menu_item, label, fid) self.on_add_cd_activate(menu_item, label, fid)
elif self.model.get_source(path) == self.model.DR: elif self.model.get_source(path) == self.model.DR:
self.on_add_directory1_activate(menu_item, filepath, label, fid) self.on_add_directory_activate(menu_item, filepath, label, fid)
return return
def on_delete1_activate(self, menu_item):
"""Main menu delete dispatcher"""
if self.view['files'].is_focus():
self.on_delete3_activate(menu_item)
if self.view['discs'].is_focus():
self.on_delete2_activate(menu_item)
if self.view['images'].is_focus():
self.on_img_delete_activate(menu_item)
def on_delete2_activate(self, menu_item): def on_delete2_activate(self, menu_item):
try: try:
selection = self.view['discs'].get_selection() selection = self.view['discs'].get_selection()
@@ -1050,6 +1123,12 @@ class MainController(Controller):
except: except:
return return
if not selected_iter:
Dialogs.Inf("Delete disc", "No disc selected",
"You have to select disc first before you " +\
"can delete it")
return
if self.model.config.confd['delwarn']: if self.model.config.confd['delwarn']:
name = model.get_value(selected_iter, 1) name = model.get_value(selected_iter, 1)
obj = Dialogs.Qst('Delete %s' % name, 'Delete %s?' % name, obj = Dialogs.Qst('Delete %s' % name, 'Delete %s?' % name,
@@ -1094,10 +1173,15 @@ class MainController(Controller):
except TypeError: except TypeError:
return return
if not list_of_paths:
Dialogs.Inf("Delete files", "No files selected",
"You have to select at least one file to delete.")
return
if self.model.config.confd['delwarn']: if self.model.config.confd['delwarn']:
obj = Dialogs.Qst("Delete elements", "Delete items?", obj = Dialogs.Qst("Delete files", "Delete files?",
"Items will be permanently \ "Selected files and directories will be" + \
removed from catalog.") " permanently\nremoved from catalog.")
if not obj.run(): if not obj.run():
return return
@@ -1156,6 +1240,14 @@ class MainController(Controller):
self.__set_title(filepath=self.model.filename, modified=True) self.__set_title(filepath=self.model.filename, modified=True)
return return
def on_edit1_activate(self, menu_item):
"""Make sufficient menu items sensitive in right cases"""
# TODO: consolidate popup-menus with edit menu
if self.view['tag_cloud_textview'].is_focus():
self.view['delete1'].set_sensitive(False)
else:
self.view['delete1'].set_sensitive(True)
def on_debugbtn_clicked(self, widget): def on_debugbtn_clicked(self, widget):
"""Debug. To remove in stable version, including button in GUI""" """Debug. To remove in stable version, including button in GUI"""
if __debug__: if __debug__:
@@ -1168,6 +1260,9 @@ class MainController(Controller):
print "abort = %s" % self.model.abort print "abort = %s" % self.model.abort
print "self.model.config.recent = %s" % self.model.config.recent print "self.model.config.recent = %s" % self.model.config.recent
print "source: %s" % self.model.source print "source: %s" % self.model.source
print "files have focus", self.view['files'].is_focus()
print "discs have focus", self.view['discs'].is_focus()
print "images have focus", self.view['images'].is_focus()
##################### #####################
@@ -1360,8 +1455,9 @@ class MainController(Controller):
def __popup_menu(self, event, menu='discs_popup'): def __popup_menu(self, event, menu='discs_popup'):
"""Popoup desired menu""" """Popoup desired menu"""
self.view[menu].popup(None, None, None, event.button, self.view[menu].popup(None, None, None, 0, 0)
event.time) #self.view[menu].popup(None, None, None, event.button,
# event.time)
self.view[menu].show_all() self.view[menu].show_all()
return return
@@ -1490,7 +1586,8 @@ class MainController(Controller):
tag.set_property('size-points', cloud['size']) tag.set_property('size-points', cloud['size'])
#tag.connect('event', self.on_tag_cloud_click, tag) #tag.connect('event', self.on_tag_cloud_click, tag)
buff.insert_with_tags(buff_iter, buff.insert_with_tags(buff_iter,
cloud['name'] + "(%d)" % cloud['count'], cloud['name'] + "(%d)" % \
cloud['count'],
tag) tag)
except: except:
if __debug__: if __debug__:

View File

@@ -222,6 +222,16 @@ class MainModel(ModelMT):
sql = """DELETE FROM tags_files WHERE file_id = ? sql = """DELETE FROM tags_files WHERE file_id = ?
AND tag_id IN """ + sql AND tag_id IN """ + sql
self.db_cursor.execute(sql, (int(file_id), )) self.db_cursor.execute(sql, (int(file_id), ))
self.db_connection.commit()
for tag_id in tag_id_list:
sql = """SELECT count(*) FROM tags_files WHERE tag_id=?"""
self.db_cursor.execute(sql, (int(tag_id),))
res = self.db_cursor.fetchone()
if res[0] == 0:
sql = """DELETE FROM tags WHERE id=?"""
self.db_cursor.execute(sql, (int(tag_id),))
self.db_connection.commit()
def get_tags(self): def get_tags(self):
"""fill tags dict with values from db""" """fill tags dict with values from db"""
@@ -793,6 +803,12 @@ class MainModel(ModelMT):
sql = """DELETE FROM tags_files WHERE file_id = ?""" sql = """DELETE FROM tags_files WHERE file_id = ?"""
db_cursor.executemany(sql, generator()) db_cursor.executemany(sql, generator())
if __debug__:
print "m_main.py: delete(): deleting:", fids
if len(fids) == 1:
arg = "(%d)" % fids[0]
else:
arg = str(tuple(fids)) arg = str(tuple(fids))
# remove thumbnails # remove thumbnails
@@ -946,6 +962,7 @@ class MainModel(ModelMT):
"""update note and description""" """update note and description"""
sql = """UPDATE files SET description=?, note=? WHERE id=?""" sql = """UPDATE files SET description=?, note=? WHERE id=?"""
self.db_cursor.execute(sql, (desc, note, file_id)) self.db_cursor.execute(sql, (desc, note, file_id))
self.db_connection.commit()
return return
# private class functions # private class functions

View File

@@ -513,13 +513,23 @@ class TagsRemoveDialog(object):
gladexml = gtk.glade.XML(self.gladefile, "tagRemove") gladexml = gtk.glade.XML(self.gladefile, "tagRemove")
dialog = gladexml.get_widget("tagRemove") dialog = gladexml.get_widget("tagRemove")
# fill model with dict # declare model
model = gtk.ListStore(gobject.TYPE_INT, model = gtk.ListStore(gobject.TYPE_INT,
gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
for tag in self.tag_dict: # sort dict
values = self.tag_dict.values()
values.sort()
keys = []
for val in values:
for d_key, d_value in self.tag_dict.items():
if d_value == val:
keys.append(d_key)
# fill model with dict
for count in range(len(keys)):
myiter = model.insert_before(None, None) myiter = model.insert_before(None, None)
model.set_value(myiter, 0, tag) model.set_value(myiter, 0, keys[count])
model.set_value(myiter, 1, self.tag_dict[tag]) model.set_value(myiter, 1, values[count])
model.set_value(myiter, 2, None) model.set_value(myiter, 2, None)
def toggle(cell, path, model): def toggle(cell, path, model):

View File

@@ -39,7 +39,6 @@ class MainView(View):
self['separatormenuitem4'].hide() self['separatormenuitem4'].hide()
self['list1'].hide() self['list1'].hide()
self['thumbnails1'].hide() self['thumbnails1'].hide()
#self['tag_cloud_textview'].drag_dest_set(0, [], 0)
return return
pass # end of class pass # end of class