dialogs now send per-dialog-window input fields as arguments to their callbacks. We
could instead allow just one of each dialog to be open, but that’s less functional.
Cross-process change tests on Quit
Though not quite as grievous, PyEdit also used to ignore changes in other open edit
windows on Quit in main windows. As a policy, on a Quit in the GUI, pop-up edit
windows destroy themselves only, but main edit windows run a tkinter quit to end the
entire program. Although all windows verify closes if their own content has changed,
other edit windows were ignored in the prior version—quitting a main window could
lose changes in other windows closed on program exit.
To do better, this version keeps a list of all open managed edit windows in the process;
on Quit in main windows it checks them all for changes, and verifies exit if any have
changed. This scheme isn’t foolproof (it doesn’t address quits run on widgets outside
PyEdit’s scope), but it is an improvement. A more ultimate solution probably involves
redefining or intercepting tkinter’s own quit method. To avoid getting too detailed
here, I’ll defer more on this topic until later in this section (see the
coverage ahead); also see the relevant comments near the end of PyEdit’s source file for
implementation notes.
New Grep dialog: Threaded and Unicode-aware file tree search
In addition, there is a new Grep option in the Search pull-down menu, which imple-
ments an external file search tool. This tool scans an entire directory tree for files whose
names match a pattern, and which contain a given search string. Names of matches are
popped up in a new nonmodal scrolled list window, with lines that identify all matches
by filename, line number, and line content. Clicking on a list item opens the matched
file in a new nonmodal and in-process PyEdit pop-up edit window and automatically
moves to and selects the line of the match. This achieves its goal by reusing much code
we wrote earlier:
- The find utility we wrote in Chapter 6 to do its tree walking
- The scrolled list utility we coded in Chapter 9 for displaying matches
- The form row builder we wrote in Chapter 10 for the nonmodal input dialog
- The existing PyEdit pop-up window mode logic to display matched files on request
- The existing PyEdit go-to callback and logic to move to the matched line in a file
To avoid blocking the GUI while files are searched during tree
walks, Grep runs searches in parallel threads. This also allows multiple greps to be
running at once and to overlap in time arbitrarily (especially useful if you grep in larger
trees, such as Python’s own library or full source trees). The standard threads, queues,
and after timer loops technique we learned in Chapter 10 is applied here—non-GUI
producer threads find matches and place them on a queue to be detected by a timer
loop in the main GUI thread.
Grep threading model.
PyEdit: A Text Editor Program/Object | 685