mirror of
https://github.com/gryf/pygtktalog.git
synced 2025-12-17 11:30:19 +01:00
* Bugfix in files removal. Controller should collect all file ids, otherwise it'll starts to remove wrong files, because in the meantime model removing items from liststore.
380 lines
14 KiB
Python
380 lines
14 KiB
Python
# This Python file uses the following encoding: utf-8
|
|
#
|
|
# Author: Roman 'gryf' Dobosz gryf@elysium.pl
|
|
#
|
|
# Copyright (C) 2007 by Roman 'gryf' Dobosz
|
|
#
|
|
# This file is part of pyGTKtalog.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
# -------------------------------------------------------------------------
|
|
|
|
import gtk
|
|
|
|
from gtkmvc import Controller
|
|
import views.v_dialogs as Dialogs
|
|
|
|
class SearchController(Controller):
|
|
"""Controller for main application window"""
|
|
|
|
def __init__(self, model):
|
|
"""Initialize controller"""
|
|
Controller.__init__(self, model)
|
|
self.search_string = ""
|
|
return
|
|
|
|
def register_view(self, view):
|
|
Controller.register_view(self, view)
|
|
|
|
# Setup TreeView result widget, as columned list
|
|
v = self.view['result']
|
|
v.set_model(self.model.search_list)
|
|
|
|
v.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
|
|
|
|
c = gtk.TreeViewColumn('Disc', gtk.CellRendererText(), text=1)
|
|
c.set_sort_column_id(1)
|
|
c.set_resizable(True)
|
|
v.append_column(c)
|
|
|
|
c = gtk.TreeViewColumn('Filename')
|
|
cellpb = gtk.CellRendererPixbuf()
|
|
cell = gtk.CellRendererText()
|
|
c.pack_start(cellpb, False)
|
|
c.pack_start(cell, True)
|
|
c.set_attributes(cellpb, stock_id=7)
|
|
c.set_attributes(cell, text=2)
|
|
c.set_sort_column_id(2)
|
|
c.set_resizable(True)
|
|
v.append_column(c)
|
|
|
|
c = gtk.TreeViewColumn('Path', gtk.CellRendererText(), text=3)
|
|
c.set_sort_column_id(3)
|
|
c.set_resizable(True)
|
|
v.append_column(c)
|
|
|
|
c = gtk.TreeViewColumn('Size', gtk.CellRendererText(), text=4)
|
|
c.set_sort_column_id(4)
|
|
c.set_resizable(True)
|
|
v.append_column(c)
|
|
|
|
c = gtk.TreeViewColumn('Date', gtk.CellRendererText(), text=5)
|
|
c.set_sort_column_id(5)
|
|
c.set_resizable(True)
|
|
v.append_column(c)
|
|
v.set_search_column(2)
|
|
|
|
# combobox
|
|
self.view['comboboxentry'].set_model(self.model.search_history)
|
|
self.view['comboboxentry'].set_text_column(0)
|
|
# statusbar
|
|
self.context_id = self.view['statusbar'].get_context_id('search')
|
|
self.view['statusbar'].pop(self.context_id)
|
|
self.view['search_window'].show()
|
|
self.model.search_created = True;
|
|
return
|
|
|
|
#########################################################################
|
|
# Connect signals from GUI, like menu objects, toolbar buttons and so on.
|
|
def on_search_window_delete_event(self, window, event):
|
|
"""if window was closed, reset attributes"""
|
|
self.model.point = None
|
|
self.model.search_created = False;
|
|
return False
|
|
|
|
def on_close_clicked(self, button):
|
|
"""close search window"""
|
|
self.model.point = None
|
|
self.model.search_created = False;
|
|
self.view['search_window'].destroy()
|
|
|
|
def on_search_activate(self, entry):
|
|
"""find button or enter pressed on entry search. Do the search"""
|
|
search_txt = self.view['search_entry'].get_text()
|
|
self.search_string = search_txt
|
|
found = self.model.search(search_txt)
|
|
self.model.add_search_history(search_txt)
|
|
self.__set_status_bar(found)
|
|
|
|
def on_result_row_activated(self, treeview, path, treecolumn):
|
|
"""result treeview row activated, change models 'point' observable
|
|
variable to id of elected item. rest is all in main controler hands."""
|
|
model = treeview.get_model()
|
|
s_iter = model.get_iter(path)
|
|
self.model.point = model.get_value(s_iter, 0)
|
|
|
|
def on_result_button_release_event(self, tree, event):
|
|
if event.button == 3: # Right mouse button. Show context menu.
|
|
try:
|
|
selection = tree.get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
except TypeError:
|
|
list_of_paths = []
|
|
|
|
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])
|
|
|
|
if len(list_of_paths) > 1:
|
|
self.view['add_image'].set_sensitive(False)
|
|
self.view['rename'].set_sensitive(False)
|
|
self.view['edit'].set_sensitive(False)
|
|
else:
|
|
self.view['add_image'].set_sensitive(True)
|
|
self.view['rename'].set_sensitive(True)
|
|
self.view['edit'].set_sensitive(True)
|
|
self.view['files_popup'].popup(None, None, None, 0, 0)
|
|
self.view['files_popup'].show_all()
|
|
return True
|
|
|
|
def on_add_tag_activate(self, menu_item):
|
|
"""Add tags to selected files"""
|
|
tags = Dialogs.TagsDialog().run()
|
|
if not tags:
|
|
return
|
|
ids = self.__get_tv_selection_ids(self.view['result'])
|
|
for item_id in ids:
|
|
self.model.add_tags(item_id, tags)
|
|
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
def on_delete_tag_activate(self, menu_item):
|
|
ids = self.__get_tv_selection_ids(self.view['result'])
|
|
if not ids:
|
|
Dialogs.Inf("Remove tags", "No files selected",
|
|
"You have to select some files first.")
|
|
return
|
|
|
|
tags = self.model.get_tags_by_file_id(ids)
|
|
if tags:
|
|
d = Dialogs.TagsRemoveDialog(tags)
|
|
retcode, retval = d.run()
|
|
if retcode=="ok" and not retval:
|
|
Dialogs.Inf("Remove tags", "No tags selected",
|
|
"You have to select any tag to remove from files.")
|
|
return
|
|
elif retcode == "ok" and retval:
|
|
self.model.delete_tags(ids, retval)
|
|
found = self.model.search(self.search_string)
|
|
self.__set_status_bar(found)
|
|
|
|
def on_add_thumb_activate(self, menu_item):
|
|
image, only_thumbs = Dialogs.LoadImageFile().run()
|
|
if not image:
|
|
return
|
|
ids = self.__get_tv_selection_ids(self.view['result'])
|
|
for item_id in ids:
|
|
self.model.add_thumbnail(image, item_id)
|
|
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
def on_remove_thumb_activate(self, menu_item):
|
|
if self.model.config.confd['delwarn']:
|
|
title = 'Delete thumbnails'
|
|
question = 'Delete thumbnails?'
|
|
description = "Thumbnails for selected items will be permanently"
|
|
description += " removed from catalog."
|
|
obj = Dialogs.Qst(title, question, description)
|
|
if not obj.run():
|
|
return
|
|
try:
|
|
ids = self.__get_tv_selection_ids(self.view['result'])
|
|
for item_id in ids:
|
|
self.model.del_thumbnail(item_id)
|
|
except:
|
|
if __debug__:
|
|
print "c_search.py: on_remove_thumb_activate(): error on",
|
|
print "getting selected items or removing thumbnails"
|
|
return
|
|
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
def on_add_image_activate(self, menu_item):
|
|
dialog = Dialogs.LoadImageFile(True)
|
|
msg = "Don't copy images. Generate only thumbnails."
|
|
toggle = gtk.CheckButton(msg)
|
|
toggle.show()
|
|
dialog.dialog.set_extra_widget(toggle)
|
|
|
|
images, only_thumbs = dialog.run()
|
|
if not images:
|
|
return
|
|
|
|
for image in images:
|
|
try:
|
|
selection = self.view['result'].get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
fid = model.get_value(model.get_iter(list_of_paths[0]), 0)
|
|
except:
|
|
try:
|
|
path, column = self.view['result'].get_cursor()
|
|
model = self.view['result'].get_model()
|
|
fiter = model.get_iter(path)
|
|
fid = model.get_value(fiter, 0)
|
|
except:
|
|
return
|
|
self.model.add_image(image, fid, only_thumbs)
|
|
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
def on_remove_image_activate(self, menu_item):
|
|
if self.model.config.confd['delwarn']:
|
|
title = 'Delete images'
|
|
question = 'Delete all images?'
|
|
description = 'All images for selected items will be permanently'
|
|
description += ' removed from catalog.'
|
|
obj = Dialogs.Qst(title, question, description)
|
|
if not obj.run():
|
|
return
|
|
try:
|
|
ids = self.__get_tv_selection_ids(self.view['result'])
|
|
for item_id in ids:
|
|
self.model.del_images(item_id)
|
|
except:
|
|
if __debug__:
|
|
print "c_search.py: on_remove_thumb_activate(): error on",
|
|
print "getting selected items or removing thumbnails"
|
|
return
|
|
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
def on_edit_activate(self, menu_item):
|
|
try:
|
|
selection = self.view['result'].get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
fid = model.get_value(model.get_iter(list_of_paths[0]), 0)
|
|
except TypeError:
|
|
if __debug__:
|
|
print "c_main.py: on_edit2_activate(): 0",
|
|
print "zaznaczonych wierszy"
|
|
return
|
|
|
|
val = self.model.get_file_info(fid)
|
|
ret = Dialogs.EditDialog(val).run()
|
|
if ret:
|
|
self.model.rename(fid, ret['filename'])
|
|
self.model.update_desc_and_note(fid,
|
|
ret['description'], ret['note'])
|
|
self.model.unsaved_project = True
|
|
|
|
def on_delete_activate(self, menu_item):
|
|
dmodel = self.model.discs_tree
|
|
try:
|
|
selection = self.view['result'].get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
except TypeError:
|
|
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']:
|
|
description = "Selected files and directories will be "
|
|
description += "permanently\n removed from catalog."
|
|
obj = Dialogs.Qst("Delete files", "Delete files?", description)
|
|
if not obj.run():
|
|
return
|
|
|
|
def foreach_searchtree(zmodel, zpath, ziter, d):
|
|
if d[0] == zmodel.get_value(ziter, 0):
|
|
d[1].append(zpath)
|
|
return False
|
|
|
|
ids = []
|
|
for p in list_of_paths:
|
|
ids.append(model.get_value(model.get_iter(p), 0))
|
|
|
|
for fid in ids:
|
|
# delete from db
|
|
self.model.delete(fid)
|
|
|
|
self.model.unsaved_project = True
|
|
found = self.model.search(self.search_string)
|
|
self.__set_status_bar(found)
|
|
return
|
|
|
|
def on_rename_activate(self, menu_item):
|
|
try:
|
|
selection = self.view['result'].get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
fid = model.get_value(model.get_iter(list_of_paths[0]), 0)
|
|
except TypeError:
|
|
if __debug__:
|
|
print "c_main.py: on_edit2_activate(): 0",
|
|
print "zaznaczonych wierszy"
|
|
return
|
|
|
|
fid = model.get_value(model.get_iter(list_of_paths[0]), 0)
|
|
name = model.get_value(model.get_iter(list_of_paths[0]),2)
|
|
new_name = Dialogs.InputNewName(name).run()
|
|
|
|
if __debug__:
|
|
print "c_search.py: on_rename_activate(): label:", new_name
|
|
|
|
if new_name and new_name != name:
|
|
self.model.rename(fid, new_name)
|
|
self.model.unsaved_project = True
|
|
return
|
|
|
|
#####################
|
|
# observed properetis
|
|
|
|
#########################
|
|
# private class functions
|
|
def __set_status_bar(self, found):
|
|
"""sets number of founded items in statusbar"""
|
|
if found == 0:
|
|
msg = "No files found."
|
|
elif found == 1:
|
|
msg = "Found 1 file."
|
|
else:
|
|
msg = "Found %d files." % found
|
|
self.view['statusbar'].push(self.context_id, "%s" % msg)
|
|
|
|
def __get_tv_selection_ids(self, treeview):
|
|
"""get selection from treeview and return coresponding ids' from
|
|
connected model or None"""
|
|
ids = []
|
|
try:
|
|
selection = treeview.get_selection()
|
|
model, list_of_paths = selection.get_selected_rows()
|
|
for path in list_of_paths:
|
|
ids.append(model.get_value(model.get_iter(path), 0))
|
|
return ids
|
|
except:
|
|
# DEBUG: treeview have no selection or smth is broken
|
|
if __debug__:
|
|
print "c_search.py: __get_tv_selection_ids(): error on",
|
|
print "getting selected items"
|
|
return
|
|
return None
|
|
|
|
pass # end of class
|