2006-08-18 Alex Roitman <shura@gramps-project.org>
* src/plugins/MediaManager.py: Add list of affected paths to the confirmation. svn: r7203
This commit is contained in:
parent
de8ba4a19d
commit
4f30e850ec
@ -1,3 +1,7 @@
|
|||||||
|
2006-08-18 Alex Roitman <shura@gramps-project.org>
|
||||||
|
* src/plugins/MediaManager.py: Add list of affected paths to the
|
||||||
|
confirmation.
|
||||||
|
|
||||||
2006-08-17 Alex Roitman <shura@gramps-project.org>
|
2006-08-17 Alex Roitman <shura@gramps-project.org>
|
||||||
* src/plugins/MediaManager.py: Change info wording.
|
* src/plugins/MediaManager.py: Change info wording.
|
||||||
* src/GrampsDb/_GrampsDbBase.py (GrampsDbBase._sortbyname): Remove
|
* src/GrampsDb/_GrampsDbBase.py (GrampsDbBase._sortbyname): Remove
|
||||||
|
@ -47,6 +47,7 @@ import gtk
|
|||||||
import GrampsDisplay
|
import GrampsDisplay
|
||||||
import Assistant
|
import Assistant
|
||||||
import Errors
|
import Errors
|
||||||
|
from RelLib import MediaObject
|
||||||
from BasicUtils import UpdateCallback
|
from BasicUtils import UpdateCallback
|
||||||
from PluginUtils import Tool, register_tool
|
from PluginUtils import Tool, register_tool
|
||||||
|
|
||||||
@ -90,7 +91,6 @@ class MediaMan(Tool.Tool):
|
|||||||
def on_before_page_next(self,obj,page,data=None):
|
def on_before_page_next(self,obj,page,data=None):
|
||||||
if page == self.selection_page:
|
if page == self.selection_page:
|
||||||
self.build_settings_page()
|
self.build_settings_page()
|
||||||
self.build_confirmation()
|
|
||||||
elif page == self.settings_page:
|
elif page == self.settings_page:
|
||||||
self.build_confirmation()
|
self.build_confirmation()
|
||||||
elif page == self.confirm_page:
|
elif page == self.confirm_page:
|
||||||
@ -106,7 +106,7 @@ class MediaMan(Tool.Tool):
|
|||||||
"the media object file: its filename and/or path, its "
|
"the media object file: its filename and/or path, its "
|
||||||
"description, its ID, notes, source references, etc. "
|
"description, its ID, notes, source references, etc. "
|
||||||
"These data <b>do not include the file itself</b>.\n\n"
|
"These data <b>do not include the file itself</b>.\n\n"
|
||||||
"The files containing image, sound, video, etc, exists "
|
"The files containing image, sound, video, etc, exist "
|
||||||
"separately on your hard drive. These files are "
|
"separately on your hard drive. These files are "
|
||||||
"not managed by GRAMPS and are not included in the GRAMPS "
|
"not managed by GRAMPS and are not included in the GRAMPS "
|
||||||
"database. "
|
"database. "
|
||||||
@ -134,8 +134,8 @@ class MediaMan(Tool.Tool):
|
|||||||
|
|
||||||
group = None
|
group = None
|
||||||
for ix in range(len(self.batch_ops)):
|
for ix in range(len(self.batch_ops)):
|
||||||
title = self.batch_ops[ix][1]
|
title = self.batch_ops[ix].title
|
||||||
description= self.batch_ops[ix][2]
|
description= self.batch_ops[ix].description
|
||||||
|
|
||||||
button = gtk.RadioButton(group,title)
|
button = gtk.RadioButton(group,title)
|
||||||
if not group:
|
if not group:
|
||||||
@ -158,8 +158,7 @@ class MediaMan(Tool.Tool):
|
|||||||
]
|
]
|
||||||
|
|
||||||
for batch_class in batches_to_use:
|
for batch_class in batches_to_use:
|
||||||
batch = batch_class()
|
self.batch_ops.append(batch_class(self.db,self.callback))
|
||||||
self.batch_ops.append(batch.get_self())
|
|
||||||
|
|
||||||
def get_selected_op_index(self):
|
def get_selected_op_index(self):
|
||||||
"""
|
"""
|
||||||
@ -184,13 +183,15 @@ class MediaMan(Tool.Tool):
|
|||||||
through the assistant).
|
through the assistant).
|
||||||
"""
|
"""
|
||||||
ix = self.get_selected_op_index()
|
ix = self.get_selected_op_index()
|
||||||
if self.batch_ops[ix][3]:
|
config = self.batch_ops[ix].build_config()
|
||||||
|
if config:
|
||||||
if ix == self.batch_settings:
|
if ix == self.batch_settings:
|
||||||
return
|
return
|
||||||
elif self.batch_settings:
|
elif self.batch_settings:
|
||||||
self.w.remove_page(self.settings_page)
|
self.w.remove_page(self.settings_page)
|
||||||
self.batch_settings = None
|
self.batch_settings = None
|
||||||
title,box = self.batch_ops[ix][3]
|
self.build_confirmation()
|
||||||
|
title,box = config
|
||||||
self.settings_page = self.w.insert_page(title,box,
|
self.settings_page = self.w.insert_page(title,box,
|
||||||
self.selection_page+1)
|
self.selection_page+1)
|
||||||
self.confirm_page += 1
|
self.confirm_page += 1
|
||||||
@ -200,29 +201,61 @@ class MediaMan(Tool.Tool):
|
|||||||
elif self.batch_settings:
|
elif self.batch_settings:
|
||||||
self.w.remove_page(self.settings_page)
|
self.w.remove_page(self.settings_page)
|
||||||
self.batch_settings = None
|
self.batch_settings = None
|
||||||
|
self.build_confirmation()
|
||||||
|
|
||||||
def build_confirmation(self):
|
def build_confirmation(self):
|
||||||
"""
|
"""
|
||||||
Build the text of the confirmation label. This should query
|
Build the confirmation page.
|
||||||
the selected options (format, filename) and present the summary
|
|
||||||
of the proposed action.
|
This should query the selected settings and present the summary
|
||||||
|
of the proposed action, as well as the list of affected paths.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ix = self.get_selected_op_index()
|
ix = self.get_selected_op_index()
|
||||||
confirm_text_builder = self.batch_ops[ix][4]
|
confirm_text = self.batch_ops[ix].build_confirm_text()
|
||||||
confirm_text = confirm_text_builder()
|
path_list = self.batch_ops[ix].build_path_list()
|
||||||
|
|
||||||
|
box = gtk.VBox()
|
||||||
|
box.set_spacing(12)
|
||||||
|
box.set_border_width(12)
|
||||||
|
|
||||||
|
label1 = gtk.Label(confirm_text)
|
||||||
|
label1.set_line_wrap(True)
|
||||||
|
label1.set_use_markup(True)
|
||||||
|
label1.set_alignment(0,0.5)
|
||||||
|
box.pack_start(label1,expand=False)
|
||||||
|
|
||||||
|
scrolled_window = gtk.ScrolledWindow()
|
||||||
|
scrolled_window.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC)
|
||||||
|
scrolled_window.set_shadow_type(gtk.SHADOW_IN)
|
||||||
|
tree = gtk.TreeView()
|
||||||
|
model = gtk.ListStore(str)
|
||||||
|
tree.set_model(model)
|
||||||
|
tree_view_column = gtk.TreeViewColumn(_('Affected path'),
|
||||||
|
gtk.CellRendererText(),text=0)
|
||||||
|
tree_view_column.set_sort_column_id(0)
|
||||||
|
tree.append_column(tree_view_column)
|
||||||
|
for path in path_list:
|
||||||
|
model.append(row=[path])
|
||||||
|
scrolled_window.add(tree)
|
||||||
|
box.pack_start(scrolled_window,expand=True,fill=True)
|
||||||
|
|
||||||
|
label3 = gtk.Label(_('Press OK to proceed, Cancel to abort, '
|
||||||
|
'or Back to revisit your options.'))
|
||||||
|
box.pack_start(label3,expand=False)
|
||||||
|
box.show_all()
|
||||||
|
|
||||||
self.w.remove_page(self.confirm_page)
|
self.w.remove_page(self.confirm_page)
|
||||||
self.confirm_page = self.w.insert_text_page(_('Final confirmation'),
|
self.confirm_page = self.w.insert_page(_('Final confirmation'),
|
||||||
confirm_text,
|
box,self.confirm_page)
|
||||||
self.confirm_page)
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
Run selected batch op with selected settings.
|
Run selected batch op with selected settings.
|
||||||
"""
|
"""
|
||||||
ix = self.get_selected_op_index()
|
ix = self.get_selected_op_index()
|
||||||
batch_op = self.batch_ops[ix][0]
|
|
||||||
self.pre_run()
|
self.pre_run()
|
||||||
success = batch_op(self.db,self.callback)
|
success = self.batch_ops[ix].run_tool()
|
||||||
self.post_run()
|
self.post_run()
|
||||||
return success
|
return success
|
||||||
|
|
||||||
@ -258,13 +291,20 @@ class MediaMan(Tool.Tool):
|
|||||||
# These are the actuall sub-tools (batch-ops) for use from Assistant
|
# These are the actuall sub-tools (batch-ops) for use from Assistant
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
class BatchOp:
|
class BatchOp(UpdateCallback):
|
||||||
"""
|
"""
|
||||||
Base class for the sub-tools.
|
Base class for the sub-tools.
|
||||||
"""
|
"""
|
||||||
title = 'Untitled operation'
|
title = 'Untitled operation'
|
||||||
description = 'This operation needs to be described'
|
description = 'This operation needs to be described'
|
||||||
|
|
||||||
|
def __init__(self,db,callback):
|
||||||
|
UpdateCallback.__init__(self,callback)
|
||||||
|
self.db = db
|
||||||
|
self.handle_list = []
|
||||||
|
self.path_list = []
|
||||||
|
self.prepared = False
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
"""
|
"""
|
||||||
This method should return either None (if the batch op requires
|
This method should return either None (if the batch op requires
|
||||||
@ -279,39 +319,78 @@ class BatchOp:
|
|||||||
"""
|
"""
|
||||||
return "This confirmation text needs to be written"
|
return "This confirmation text needs to be written"
|
||||||
|
|
||||||
def run_tool(self,db,callback):
|
def build_path_list(self):
|
||||||
self._prepare(db,callback)
|
"""
|
||||||
success = self._run(db)
|
This method returns a list of the path names that would be
|
||||||
self._cleanup(db)
|
affected by the batch op. Typically it would rely on prepare()
|
||||||
|
to do the actual job, but it does not have to be that way.
|
||||||
|
"""
|
||||||
|
self.prepare()
|
||||||
|
return self.path_list
|
||||||
|
|
||||||
|
def run_tool(self):
|
||||||
|
"""
|
||||||
|
This method runs the batch op, taking care of database signals
|
||||||
|
and transactions before and after the running.
|
||||||
|
Should not be overridden without good reasons.
|
||||||
|
"""
|
||||||
|
self._pre_run()
|
||||||
|
success = self._run()
|
||||||
|
self._post_run()
|
||||||
return success
|
return success
|
||||||
|
|
||||||
def _prepare(self,db,callback):
|
def _pre_run(self):
|
||||||
uc = UpdateCallback(callback)
|
"""
|
||||||
uc.set_total(db.get_number_of_media_objects())
|
Low-level method for starting transaction and disabling signals.
|
||||||
self.update = uc.update
|
Should not be overridden without good reasons.
|
||||||
self.trans = db.transaction_begin("",batch=True)
|
"""
|
||||||
db.disable_signals()
|
self.trans = self.db.transaction_begin("",batch=True)
|
||||||
|
self.db.disable_signals()
|
||||||
|
|
||||||
def _cleanup(self,db):
|
def _post_run(self):
|
||||||
db.transaction_commit(self.trans,self.title)
|
"""
|
||||||
db.enable_signals()
|
Low-level method for committing transaction and enabling signals.
|
||||||
db.request_rebuild()
|
Should not be overridden without good reasons.
|
||||||
|
"""
|
||||||
|
self.db.transaction_commit(self.trans,self.title)
|
||||||
|
self.db.enable_signals()
|
||||||
|
self.db.request_rebuild()
|
||||||
|
|
||||||
def _run(self,db,callback):
|
def _run(self):
|
||||||
|
"""
|
||||||
|
This method is the beef of the tool.
|
||||||
|
Needs to be overridden in the subclass.
|
||||||
|
"""
|
||||||
|
print "This method needs to be written."
|
||||||
print "Running BatchOp tool... done."
|
print "Running BatchOp tool... done."
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_self(self):
|
def prepare(self):
|
||||||
return (self.run_tool,self.title,self.description,
|
"""
|
||||||
self.build_config(),self.build_confirm_text)
|
This method should prepare the tool for the actual run.
|
||||||
|
Typically this involves going over media objects and
|
||||||
|
selecting the ones that will be affected by the batch op.
|
||||||
|
|
||||||
|
This method should set self.prepared to True, to indicate
|
||||||
|
that it has already ran.
|
||||||
|
"""
|
||||||
|
self.prepared = True
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
# Simple op to replace substrings in the paths
|
||||||
|
#------------------------------------------------------------------------
|
||||||
class PathChange(BatchOp):
|
class PathChange(BatchOp):
|
||||||
title = _('Change path')
|
title = _('Replace substrings in the path')
|
||||||
description = _('This tool allows changing specified path '
|
description = _('This tool allows replacing specified substring in the '
|
||||||
'into another specified path')
|
'path of media objects with another substring. '
|
||||||
|
'This can be useful when you move your media files '
|
||||||
|
'from one directory to another')
|
||||||
|
|
||||||
|
def __init__(self,db,callback):
|
||||||
|
BatchOp.__init__(self,db,callback)
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
title = _("Change path settings")
|
title = _("Replace substring settings")
|
||||||
|
|
||||||
box = gtk.VBox()
|
box = gtk.VBox()
|
||||||
box.set_spacing(12)
|
box.set_spacing(12)
|
||||||
@ -347,20 +426,39 @@ class PathChange(BatchOp):
|
|||||||
to_text = unicode(self.to_entry.get_text())
|
to_text = unicode(self.to_entry.get_text())
|
||||||
text = _(
|
text = _(
|
||||||
'The following action is to be performed:\n\n'
|
'The following action is to be performed:\n\n'
|
||||||
'Operation:\t%s\nReplace:\t\t%s\nWith:\t\t%s\n\n'
|
'Operation:\t%s\nReplace:\t\t%s\nWith:\t\t%s'
|
||||||
'Press OK to proceed, Cancel to abort, or Back to '
|
) % (self.title, from_text, to_text)
|
||||||
'revisit your options.') % (self.title, from_text, to_text)
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def _run(self,db):
|
def prepare(self):
|
||||||
|
from_text = unicode(self.from_entry.get_text())
|
||||||
|
cursor = self.db.get_media_cursor()
|
||||||
|
self.set_total(self.db.get_number_of_media_objects())
|
||||||
|
item = cursor.first()
|
||||||
|
while item:
|
||||||
|
(handle,data) = item
|
||||||
|
obj = MediaObject()
|
||||||
|
obj.unserialize(data)
|
||||||
|
if obj.get_path().find(from_text) != -1:
|
||||||
|
self.handle_list.append(handle)
|
||||||
|
self.path_list.append(obj.path)
|
||||||
|
item = cursor.next()
|
||||||
|
self.update()
|
||||||
|
cursor.close()
|
||||||
|
self.reset()
|
||||||
|
self.prepared = True
|
||||||
|
|
||||||
|
def _run(self):
|
||||||
|
if not self.prepared:
|
||||||
|
self.prepare()
|
||||||
|
self.set_total(len(self.handle_list))
|
||||||
from_text = unicode(self.from_entry.get_text())
|
from_text = unicode(self.from_entry.get_text())
|
||||||
to_text = unicode(self.to_entry.get_text())
|
to_text = unicode(self.to_entry.get_text())
|
||||||
for handle in db.get_media_object_handles():
|
for handle in self.handle_list:
|
||||||
obj = db.get_object_from_handle(handle)
|
obj = self.db.get_object_from_handle(handle)
|
||||||
if obj.get_path().find(from_text) != -1:
|
new_path = obj.get_path().replace(from_text,to_text)
|
||||||
new_path = obj.get_path().replace(from_text,to_text)
|
obj.set_path(new_path)
|
||||||
obj.set_path(new_path)
|
self.db.commit_media_object(obj,self.trans)
|
||||||
db.commit_media_object(obj,self.trans)
|
|
||||||
self.update()
|
self.update()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user