Edit book: When doing a Replace/Count all with multiple searches add a Show details button on the result dialog that shows the individual counts for each search.

This commit is contained in:
Kovid Goyal 2017-07-02 17:42:53 +05:30
parent 48b3bdf0f3
commit ed554fd319
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -5,7 +5,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
import copy import copy
import json import json
from collections import OrderedDict from collections import OrderedDict, Counter
from functools import partial from functools import partial
from PyQt5.Qt import ( from PyQt5.Qt import (
@ -1315,6 +1315,10 @@ def get_search_function(state):
return ans return ans
def get_search_name(state):
return state.get('name', state['find'])
def initialize_search_request(state, action, current_editor, current_editor_name, searchable_names): def initialize_search_request(state, action, current_editor, current_editor_name, searchable_names):
editor = None editor = None
where = state['where'] where = state['where']
@ -1384,6 +1388,8 @@ def run_search(
if len(searches) > 1: if len(searches) > 1:
errfind = _('the selected searches') errfind = _('the selected searches')
search_names = [get_search_name(search) for search in searches]
try: try:
searches = [(get_search_regex(search), get_search_function(search)) for search in searches] searches = [(get_search_regex(search), get_search_function(search)) for search in searches]
except InvalidRegex as e: except InvalidRegex as e:
@ -1451,24 +1457,29 @@ def run_search(
return no_replace(_( return no_replace(_(
'Currently selected text does not match the search query.')) 'Currently selected text does not match the search query.'))
def count_message(replaced, count, show_diff=False, show_dialog=True): def count_message(replaced, count, show_diff=False, show_dialog=True, count_map=None):
if show_dialog: if show_dialog:
if replaced: if replaced:
msg = _('Performed the replacement at {num} occurrences of {query}') msg = _('Performed the replacement at {num} occurrences of {query}')
else: else:
msg = _('Found {num} occurrences of {query}') msg = _('Found {num} occurrences of {query}')
msg = msg.format(num=count, query=errfind) msg = msg.format(num=count, query=errfind)
det_msg = ''
if count_map is not None and count > 0 and len(count_map) > 1:
for k in sorted(count_map):
det_msg += _('{0}: {1} occurrences').format(k, count_map[k]) + '\n'
if show_diff and count > 0: if show_diff and count > 0:
d = MessageBox(MessageBox.INFO, _('Searching done'), prepare_string_for_xml(msg), parent=gui_parent, show_copy_button=False) d = MessageBox(MessageBox.INFO, _('Searching done'), prepare_string_for_xml(msg), parent=gui_parent, show_copy_button=False, det_msg=det_msg)
d.diffb = b = d.bb.addButton(_('See what &changed'), d.bb.ActionRole) d.diffb = b = d.bb.addButton(_('See what &changed'), d.bb.ActionRole)
b.setIcon(QIcon(I('diff.png'))), d.set_details(None), b.clicked.connect(d.accept) b.setIcon(QIcon(I('diff.png'))), d.set_details(None), b.clicked.connect(d.accept)
b.clicked.connect(partial(show_current_diff, allow_revert=True), type=Qt.QueuedConnection) b.clicked.connect(partial(show_current_diff, allow_revert=True), type=Qt.QueuedConnection)
d.exec_() d.exec_()
else: else:
info_dialog(gui_parent, _('Searching done'), prepare_string_for_xml(msg), show=True) info_dialog(gui_parent, _('Searching done'), prepare_string_for_xml(msg), show=True, det_msg=det_msg)
def do_all(replace=True): def do_all(replace=True):
count = 0 count = 0
count_map = Counter()
if not files and editor is None: if not files and editor is None:
return 0 return 0
lfiles = files or {current_editor_name:editor.syntax} lfiles = files or {current_editor_name:editor.syntax}
@ -1481,7 +1492,7 @@ def run_search(
raw = current_container().raw_data(n) raw = current_container().raw_data(n)
raw_data[n] = raw raw_data[n] = raw
for p, repl in searches: for search_name, (p, repl) in zip(search_names, searches):
repl_is_func = isinstance(repl, Function) repl_is_func = isinstance(repl, Function)
file_iterator = lfiles file_iterator = lfiles
if repl_is_func: if repl_is_func:
@ -1500,6 +1511,7 @@ def run_search(
else: else:
num = len(p.findall(raw)) num = len(p.findall(raw))
count += num count += num
count_map[search_name] += num
if repl_is_func: if repl_is_func:
repl.end() repl.end()
show_function_debug_output(repl) show_function_debug_output(repl)
@ -1512,7 +1524,7 @@ def run_search(
with current_container().open(n, 'wb') as f: with current_container().open(n, 'wb') as f:
f.write(raw.encode('utf-8')) f.write(raw.encode('utf-8'))
QApplication.restoreOverrideCursor() QApplication.restoreOverrideCursor()
count_message(replace, count, show_diff=replace) count_message(replace, count, show_diff=replace, count_map=count_map)
return count return count
with BusyCursor(): with BusyCursor():