~sir-rainbow/+junk/scribes-on-win

« back to all changes in this revision

Viewing changes to plugins/SearchReplace/Manager.py

  • Committer: goldenmyst
  • Date: 2007-09-25 17:15:52 UTC
  • Revision ID: goldenmyst@goldenmyst-desktop-20070925171552-mvrhxdd39iibs0sr
New branch. New Trigger Management System. New Trigger API. New Plugin Management System. Fix for bug triggered by PyGTK+ version 2.11 or better.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
# Copyright © 2005 Lateef Alabi-Oki
 
3
#
 
4
# This file is part of Scribes.
 
5
#
 
6
# Scribes is free software; you can redistribute it and/or modify
 
7
# it under the terms of the GNU General Public License as published by
 
8
# the Free Software Foundation; either version 2 of the License, or
 
9
# (at your option) any later version.
 
10
#
 
11
# Scribes is distributed in the hope that it will be useful,
 
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
# GNU General Public License for more details.
 
15
#
 
16
# You should have received a copy of the GNU General Public License
 
17
# along with Scribes; if not, write to the Free Software
 
18
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 
19
# USA
 
20
 
 
21
"""
 
22
This module documents a class that creates an object that searches for,
 
23
or replaces, text found in the text editor's buffer.
 
24
 
 
25
@author: Lateef Alabi-Oki
 
26
@organization: The Scribes Project
 
27
@copyright: Copyright © 2005 Lateef Alabi-Oki
 
28
@license: GNU GPLv2 or Later
 
29
@contact: mystilleef@gmail.com
 
30
"""
 
31
 
 
32
from gobject import GObject, SIGNAL_RUN_LAST, TYPE_NONE
 
33
 
 
34
class SearchReplaceManager(GObject):
 
35
        """
 
36
        This class implements and object that searches for, or replaces,
 
37
        text found in the text editor's buffer.
 
38
        """
 
39
 
 
40
        __gsignals__ = {
 
41
                "matches-found": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
42
                "no-matches-found": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
43
                "searching": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
44
                "next": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
45
                "previous": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
46
                "cancel": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
47
                "updated-queries": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
48
                "replacing": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
49
                "replaced": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
50
                "replaced-all": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
51
                "destroy": (SIGNAL_RUN_LAST, TYPE_NONE, ()),
 
52
        }
 
53
 
 
54
        def __init__(self, editor):
 
55
                """
 
56
                Initialize the object.
 
57
 
 
58
                @param self: Reference to the SearchReplaceManager instance.
 
59
                @type self: A SearchReplaceManager object.
 
60
 
 
61
                @param editor: Reference to the text editor.
 
62
                @type editor: An Editor object.
 
63
                """
 
64
                GObject.__init__(self)
 
65
                self.__init_attributes(editor)
 
66
                self.__store_id = self.__editor.store.add_object("SearchReplaceManager", self)
 
67
                self.__signal_id_1 = self.connect("searching", self.__search_searching_cb)
 
68
                self.__signal_id_2 = self.connect("matches-found", self.__search_matches_found_cb)
 
69
                self.__signal_id_3 = self.connect("no-matches-found", self.__search_no_matches_found_cb)
 
70
                self.__signal_id_4 = self.connect("next", self.__search_next_cb)
 
71
                self.__signal_id_5 = self.connect("previous", self.__search_previous_cb)
 
72
                self.__signal_id_6 = self.connect("cancel", self.__search_cancel_cb)
 
73
                self.__signal_id_7 = self.connect("replacing", self.__search_replacing_cb)
 
74
                self.__signal_id_8 = self.connect("replaced", self.__search_replaced_cb)
 
75
                self.__signal_id_9 = self.connect("replaced-all", self.__search_replace_all_cb)
 
76
                self.__signal_id_10 = editor.connect("hide-bar", self.__search_hide_bar_cb)
 
77
                self.__signal_id_11 = editor.connect("show-bar", self.__search_show_bar_cb)
 
78
                self.__signal_id_12 = self.connect("destroy", self.__destroy_cb)
 
79
                self.__gconf_client.notify_add("/apps/scribes/match_case", self.__search_client_cb)
 
80
                self.__gconf_client.notify_add("/apps/scribes/match_word", self.__search_client_cb)
 
81
 
 
82
        def __init_attributes(self, editor):
 
83
                """
 
84
                Initialize data attributes for the object.
 
85
 
 
86
                @param self: Reference to the SearchReplaceManager instance.
 
87
                @type self: A SearchReplaceManager object.
 
88
 
 
89
                @param editor: Reference to the text editor.
 
90
                @type editor: An Editor object.
 
91
                """
 
92
                self.__editor = editor
 
93
                self.__queries = []
 
94
                self.__start_point_mark = None
 
95
                self.__end_point_mark = None
 
96
                self.__index = None
 
97
                self.__number_of_matches = None
 
98
                self.__position_of_matches = []
 
99
                self.__match_tag = self.__create_match_tag()
 
100
                self.__selection_tag = self.__create_selection_tag()
 
101
                self.__replace_tag = self.__create_replace_tag()
 
102
                self.__cancel_search_operation = False
 
103
                self.__cancel_replace_operation = False
 
104
                self.__enable_regular_expression = False
 
105
                self.__enable_incremental_search = False
 
106
                self.__reset_flag = True
 
107
                from gconf import client_get_default
 
108
                self.__gconf_client = client_get_default()
 
109
                self.__match_case = self.__gconf_client.get_bool("/apps/scribes/match_case")
 
110
                self.__match_word = self.__gconf_client.get_bool("/apps/scribes/match_word")
 
111
                self.__is_initialized = True
 
112
                self.__bar_is_visible = False
 
113
                self.__status_id = None
 
114
                self.__signal_id_1 = self.__signal_id_2 = self.__signal_id_3 = None
 
115
                self.__signal_id_4 = self.__signal_id_5 = self.__signal_id_6 = None
 
116
                self.__signal_id_7 = self.__signal_id_8 = self.__signal_id_9 = None
 
117
                self.__signal_id_10 = self.__signal_id_11 = self.__signal_id_12 = None
 
118
                self.__store_id = None
 
119
                return
 
120
 
 
121
        def __get_index(self):
 
122
                return self.__index
 
123
 
 
124
        def __get_number_of_matches(self):
 
125
                return self.__number_of_matches
 
126
 
 
127
        def __get_queries(self):
 
128
                return self.__queries
 
129
 
 
130
        def __get_is_initialized(self):
 
131
                return self.__is_initialized
 
132
 
 
133
########################################################################
 
134
#
 
135
#                                               Public Search Methods
 
136
#
 
137
########################################################################
 
138
 
 
139
        # Public API property.
 
140
        index = property(__get_index, doc="")
 
141
        number_of_matches = property(__get_number_of_matches, doc="Number of match found")
 
142
        queries = property(__get_queries, doc="")
 
143
        is_initialized = property(__get_is_initialized, doc="")
 
144
 
 
145
        def find(self, string, start, end):
 
146
                """
 
147
                Search the text editor's buffer for a string.
 
148
 
 
149
                @param self: Reference to the SearchReplaceManager instance.
 
150
                @type self: A SearchReplaceManager object.
 
151
 
 
152
                @param string: A string in the buffer to search for.
 
153
                @type string: A String object.
 
154
                """
 
155
                self.__start_point_mark = start
 
156
                self.__end_point_mark = end
 
157
                self.__reset_flag = False
 
158
                self.__cancel_search_operation = False
 
159
                self.emit("searching")
 
160
                if not string in self.__queries:
 
161
                        self.__queries.append(string)
 
162
                        self.emit("updated-queries")
 
163
                else:
 
164
                        self.__queries.remove(string)
 
165
                        self.__queries.append(string)
 
166
#               begin, end = self.__editor.textbuffer.get_bounds()
 
167
                found_matches = self.__search_for_matches(string)
 
168
                if self.__cancel_search_operation:
 
169
                        self.__reset()
 
170
                        return
 
171
                if found_matches:
 
172
                        self.__position_of_matches = found_matches
 
173
                        self.emit("matches-found")
 
174
                else:
 
175
                        if self.__cancel_search_operation:
 
176
                                self.__reset()
 
177
                                return
 
178
                        self.emit("no-matches-found")
 
179
                return
 
180
 
 
181
        def search(self, string, start, end):
 
182
                self.find(string, start, end)
 
183
                return
 
184
 
 
185
        def next(self):
 
186
                """
 
187
                Move the selection tag to the next match.
 
188
 
 
189
                @param self: Reference to the SearchReplaceManager instance.
 
190
                @type self: A SearchReplaceManager object.
 
191
                """
 
192
                self.emit("next")
 
193
                return
 
194
 
 
195
        def previous(self):
 
196
                """
 
197
                Move the selection tag to the previous match.
 
198
 
 
199
                @param self: Reference to the SearchReplaceManager instance.
 
200
                @type self: A SearchReplaceManager object.
 
201
                """
 
202
                self.emit("previous")
 
203
                return
 
204
 
 
205
########################################################################
 
206
#
 
207
#                                               Public Replace Methods
 
208
#
 
209
########################################################################
 
210
 
 
211
        def replace(self, text):
 
212
                """
 
213
                Replace selected text in the text editor's buffer.
 
214
 
 
215
                @param self: Reference to the Replace instance.
 
216
                @type self: A Replace object.
 
217
                """
 
218
                self.__reset_flag = False
 
219
                self.__cancel_replace_operation = False
 
220
                self.emit("replacing")
 
221
                begin, end = self.__position_of_matches[self.__index]
 
222
                textbuffer = self.__editor.textbuffer
 
223
                begin_mark = textbuffer.create_mark(None, begin, True)
 
224
                self.__reset()
 
225
                textbuffer.begin_user_action()
 
226
                textbuffer.delete(begin, end)
 
227
                begin = textbuffer.get_iter_at_mark(begin_mark)
 
228
                textbuffer.insert_with_tags(begin, text, self.__replace_tag)
 
229
                textbuffer.end_user_action()
 
230
                if begin_mark.get_deleted() is False:
 
231
                        textbuffer.delete_mark(begin_mark)
 
232
                self.emit("replaced")
 
233
                return
 
234
 
 
235
        def replace_all(self, text):
 
236
                """
 
237
                Replace all selected text in the text editor's buffer.
 
238
 
 
239
                @param self: Reference to the Replace instance.
 
240
                @type self: A Replace object.
 
241
                """
 
242
                self.__reset_flag = False
 
243
                self.__cancel_replace_operation = False
 
244
                self.emit("replacing")
 
245
                position_marks = []
 
246
                textbuffer = self.__editor.textbuffer
 
247
                def delete_marks():
 
248
                        for item in position_marks:
 
249
                                if item[0].get_deleted() is False:
 
250
                                        textbuffer.delete_mark(item[0])
 
251
                                if item[1].get_deleted() is False:
 
252
                                        textbuffer.delete_mark(item[1])
 
253
                from SCRIBES.utils import response
 
254
                for position in self.__position_of_matches:
 
255
                        response()
 
256
                        mark_begin = textbuffer.create_mark(None, position[0], True)
 
257
                        mark_end = textbuffer.create_mark(None, position[1], False)
 
258
                        position_marks.append((mark_begin, mark_end))
 
259
                        if self.__cancel_replace_operation:
 
260
                                delete_marks()
 
261
                                self.__reset()
 
262
                                return
 
263
                self.__reset()
 
264
                from SCRIBES.cursor import move_view_to_cursor
 
265
                textbuffer.begin_user_action()
 
266
                for position in position_marks:
 
267
                        response()
 
268
                        if self.__cancel_replace_operation:
 
269
                                delete_marks()
 
270
                                return
 
271
                        begin = textbuffer.get_iter_at_mark(position[0])
 
272
                        end = textbuffer.get_iter_at_mark(position[1])
 
273
                        textbuffer.delete(begin, end)
 
274
                        begin = textbuffer.get_iter_at_mark(position[0])
 
275
                        textbuffer.place_cursor(begin)
 
276
                        textbuffer.insert_with_tags(begin, text, self.__replace_tag)
 
277
                        move_view_to_cursor(self.__editor.textview)
 
278
                textbuffer.end_user_action()
 
279
                delete_marks()
 
280
                if self.__cancel_replace_operation:
 
281
                        self.__reset()
 
282
                        return
 
283
                self.emit("replaced-all")
 
284
                return
 
285
 
 
286
########################################################################
 
287
#
 
288
#                                                       Public Methods
 
289
#
 
290
########################################################################
 
291
 
 
292
        def cancel(self):
 
293
                """
 
294
                Cancel a search operation.
 
295
 
 
296
                @param self: Reference to the SearchReplaceManager instance.
 
297
                @type self: A SearchReplaceManager object.
 
298
                """
 
299
                self.emit("cancel")
 
300
                return
 
301
 
 
302
        def reset(self):
 
303
                """
 
304
                Reset the search processor's state.
 
305
 
 
306
                @param self: Reference to the SearchReplaceManager instance.
 
307
                @type self: A SearchReplaceManager object.
 
308
                """
 
309
                self.__reset()
 
310
                return
 
311
 
 
312
        def enable_incremental_searching(self, value=True):
 
313
                """
 
314
                Enable or disable incremental searching.
 
315
 
 
316
                @param self: Reference to the SearchReplaceManager instance.
 
317
                @type self: A SearchReplaceManager object.
 
318
 
 
319
                @param value: True to enable incremental searching.
 
320
                @type value: A Boolean object.
 
321
                """
 
322
                if value is True or value is False:
 
323
                        self.__enable_incremental_search = value
 
324
                return
 
325
 
 
326
        def get_queries(self):
 
327
                """
 
328
                Return a list of search queries.
 
329
 
 
330
                @param self: Reference to the SearchReplaceManager instance.
 
331
                @type self: A SearchReplaceManager object.
 
332
 
 
333
                @return: A list of search queries.
 
334
                @rtype: A List object.
 
335
                """
 
336
                return self.__queries
 
337
 
 
338
        def is_initialized(self):
 
339
                return self.__is_initialized
 
340
 
 
341
########################################################################
 
342
#
 
343
#                                               Tags for Matches
 
344
#
 
345
########################################################################
 
346
 
 
347
        def __create_match_tag(self):
 
348
                """
 
349
                Create the search processor's match tag.
 
350
 
 
351
                @param self: Reference to the SearchReplaceManager instance.
 
352
                @type self: A SearchReplaceManager object.
 
353
                """
 
354
                tag = self.__editor.textbuffer.create_tag()
 
355
                tag.set_property("background", "yellow")
 
356
                tag.set_property("foreground", "blue")
 
357
                from pango import WEIGHT_BOLD
 
358
                tag.set_property("weight", WEIGHT_BOLD)
 
359
                return tag
 
360
 
 
361
        def __create_selection_tag(self):
 
362
                """
 
363
                Create the search processor's selection tag
 
364
 
 
365
                @param self: Reference to the SearchReplaceManager instance.
 
366
                @type self: A SearchReplaceManager object.
 
367
                """
 
368
                tag = self.__editor.textbuffer.create_tag()
 
369
                tag.set_property("background", "blue")
 
370
                tag.set_property("foreground", "yellow")
 
371
                from pango import WEIGHT_HEAVY
 
372
                tag.set_property("weight", WEIGHT_HEAVY)
 
373
                return tag
 
374
 
 
375
        def __create_replace_tag(self):
 
376
                """
 
377
                Create the replace tag for the Replace object.
 
378
 
 
379
                @param self: Reference to the Replace instance.
 
380
                @type self: A Replace object.
 
381
                """
 
382
                tag = self.__editor.textbuffer.create_tag()
 
383
                tag.set_property("background", "green")
 
384
                tag.set_property("foreground", "blue")
 
385
                from pango import WEIGHT_HEAVY
 
386
                tag.set_property("weight", WEIGHT_HEAVY)
 
387
                return tag
 
388
 
 
389
########################################################################
 
390
#
 
391
#                                                       Search Algorithm
 
392
#
 
393
########################################################################
 
394
 
 
395
        def __search_for_matches(self, string):
 
396
                """
 
397
                Search the text editor's buffer for a string.
 
398
 
 
399
                @param self: Reference to the SearchReplaceManager instance.
 
400
                @type self: A SearchReplaceManager object.
 
401
 
 
402
                @param string: The string to search for.
 
403
                @type string: A String object.
 
404
                """
 
405
                begin = self.__editor.textbuffer.get_iter_at_mark(self.__start_point_mark)
 
406
                end = self.__editor.textbuffer.get_iter_at_mark(self.__end_point_mark)
 
407
                if self.__enable_incremental_search:
 
408
                        from SCRIBES.cursor import get_cursor_iterator
 
409
                        begin = get_cursor_iterator(self.__editor.textbuffer)
 
410
                        self.__editor.textbuffer.move_mark(self.__start_point_mark, begin)
 
411
                text = self.__editor.textbuffer.get_text(begin, end)
 
412
                found_matches = []
 
413
                from re import UNICODE, findall, escape, MULTILINE, IGNORECASE
 
414
                if self.__enable_regular_expression:
 
415
                        if self.__match_case:
 
416
                                matches = findall(string, text, UNICODE|MULTILINE)
 
417
                        else:
 
418
                                matches = findall(string, text, UNICODE|MULTILINE|IGNORECASE)
 
419
                else:
 
420
                        if self.__match_case:
 
421
                                matches = findall(escape(string), text, UNICODE|MULTILINE)
 
422
                        else:
 
423
                                matches = findall(escape(string), text, UNICODE|MULTILINE|IGNORECASE)
 
424
                if not matches:
 
425
                        return None
 
426
                found_matches = self.__get_positions(matches)
 
427
                return found_matches
 
428
 
 
429
        def __get_positions(self, matches):
 
430
                """
 
431
                Get position of found matches in the buffer.
 
432
 
 
433
                @param self: Reference to the SearchReplaceManager instance.
 
434
                @type self: A SearchReplaceManager object.
 
435
 
 
436
                @param matches: Found matches.
 
437
                @type matches: A List object.
 
438
 
 
439
                @return: Position of found matches in the text editor's buffer.
 
440
                @rtype: A List object.
 
441
                """
 
442
                positions = []
 
443
                begin = self.__editor.textbuffer.get_iter_at_mark(self.__start_point_mark)
 
444
                end = self.__editor.textbuffer.get_iter_at_mark(self.__end_point_mark)
 
445
                from gtk import TEXT_SEARCH_VISIBLE_ONLY
 
446
                from SCRIBES.utils import response
 
447
                for match in matches:
 
448
                        if self.__cancel_search_operation:
 
449
                                return None
 
450
                        response()
 
451
                        start, stop = begin.forward_search(match, TEXT_SEARCH_VISIBLE_ONLY, end)
 
452
                        positions.append((start, stop))
 
453
                        begin = stop
 
454
                if self.__match_word and self.__enable_regular_expression is False:
 
455
                        temp = []
 
456
                        for start, stop in positions:
 
457
                                if start.starts_word() and stop.ends_word():
 
458
                                        temp.append((start, stop))
 
459
                        positions = temp
 
460
                return positions
 
461
 
 
462
########################################################################
 
463
#
 
464
#                                               Event and Signal Handlers
 
465
#
 
466
########################################################################
 
467
 
 
468
        def __search_searching_cb(self, SearchReplaceManager):
 
469
                """
 
470
                Handles callback when the "searching" signal is emitted.
 
471
 
 
472
                @param self: Reference to the SearchReplaceManager instance.
 
473
                @type self: A SearchReplaceManager object.
 
474
 
 
475
                @param SearchReplaceManager: The text editor's search processor.
 
476
                @type SearchReplaceManager: A SearchReplaceManager object.
 
477
                """
 
478
                from i18n import msg0001
 
479
                if self.__status_id:
 
480
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
481
                self.__status_id = self.__editor.feedback.set_modal_message(msg0001, "run")
 
482
                return
 
483
 
 
484
        def __search_matches_found_cb(self, SearchReplaceManager):
 
485
                """
 
486
                Handles callback when the "matches-found" signal is emitted.
 
487
 
 
488
                @param self: Reference to the SearchReplaceManager instance.
 
489
                @type self: A SearchReplaceManager object.
 
490
 
 
491
                @param SearchReplaceManager: The text editor's search processor.
 
492
                @type SearchReplaceManager: A SearchReplaceManager object.
 
493
                """
 
494
                self.__reset_flag = False
 
495
                if self.__cancel_search_operation:
 
496
                        return
 
497
                self.__index = 0
 
498
                self.__number_of_matches = len(self.__position_of_matches)
 
499
                for position in self.__position_of_matches:
 
500
                        if self.__cancel_search_operation:
 
501
                                return
 
502
                        self.__editor.textbuffer.apply_tag(self.__match_tag, position[0], position[1])
 
503
                begin, end = self.__position_of_matches[self.__index]
 
504
                self.__editor.textbuffer.place_cursor(begin)
 
505
                self.__editor.textbuffer.apply_tag(self.__selection_tag, begin, end)
 
506
                from SCRIBES.cursor import move_view_to_cursor
 
507
                move_view_to_cursor(self.__editor.textview)
 
508
                # Send feedback to the status bar.
 
509
                if self.__status_id:
 
510
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
511
                from i18n import msg0002, msg0003
 
512
                message = msg0003 % (self.__index+1, self.__number_of_matches)
 
513
                self.__status_id = self.__editor.feedback.set_modal_message(message, "find")
 
514
                message = msg0002 % self.__number_of_matches
 
515
                self.__editor.feedback.update_status_message(message, "succeed", 10)
 
516
                return
 
517
 
 
518
        def __search_no_matches_found_cb(self, SearchReplaceManager):
 
519
                """
 
520
                Handles callback when the "no-matches-found" signal is emitted.
 
521
 
 
522
                @param self: Reference to the SearchReplaceManager instance.
 
523
                @type self: A SearchReplaceManager object.
 
524
 
 
525
                @param SearchReplaceManager: The text editor's SearchReplaceManager.
 
526
                @type SearchReplaceManager: A SearchReplaceManager object.
 
527
                """
 
528
                self.__reset()
 
529
                from i18n import msg0004
 
530
                self.__editor.feedback.update_status_message(msg0004, "warning", 10)
 
531
                return
 
532
 
 
533
        def __search_next_cb(self, SearchReplaceManager):
 
534
                """
 
535
                Handles callback when the "next" signal is emitted.
 
536
 
 
537
                @param self: Reference to the SearchReplaceManager instance.
 
538
                @type self: A SearchReplaceManager object.
 
539
 
 
540
                @param SearchReplaceManager: The text editor's SearchReplaceManager.
 
541
                @type SearchReplaceManager: A SearchReplaceManager object.
 
542
                """
 
543
                self.__reset_flag = False
 
544
                if self.__index >= self.__number_of_matches - 1:
 
545
                        from i18n import msg0005
 
546
                        self.__editor.feedback.update_status_message(msg0005, "warning")
 
547
                        return
 
548
                begin, end = self.__editor.textbuffer.get_bounds()
 
549
                self.__editor.textbuffer.remove_tag(self.__selection_tag, begin, end)
 
550
                self.__index += 1
 
551
                begin, end = self.__position_of_matches[self.__index]
 
552
                self.__editor.textbuffer.place_cursor(begin)
 
553
                self.__editor.textbuffer.apply_tag(self.__selection_tag, begin, end)
 
554
                from SCRIBES.cursor import move_view_to_cursor
 
555
                move_view_to_cursor(self.__editor.textview)
 
556
                if self.__status_id:
 
557
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
558
                from i18n import msg0003
 
559
                message = msg0003 % (self.__index+1, self.__number_of_matches)
 
560
                self.__status_id = self.__editor.feedback.set_modal_message(message, "find")
 
561
                return
 
562
 
 
563
        def __search_previous_cb(self, SearchReplaceManager):
 
564
                """
 
565
                Handles callback when the "previous" signal is emitted.
 
566
 
 
567
                @param self: Reference to the SearchReplaceManager instance.
 
568
                @type self: A SearchReplaceManager object.
 
569
 
 
570
                @param SearchReplaceManager: The text editor's SearchReplaceManager.
 
571
                @type SearchReplaceManager: A SearchReplaceManager object.
 
572
                """
 
573
                self.__reset_flag = False
 
574
                if self.__index <= 0:
 
575
                        from i18n import msg0010
 
576
                        self.__editor.feedback.update_status_message(msg0010, "warning")
 
577
                        return
 
578
                begin, end = self.__editor.textbuffer.get_bounds()
 
579
                self.__editor.textbuffer.remove_tag(self.__selection_tag, begin, end)
 
580
                self.__index -= 1
 
581
                begin, end = self.__position_of_matches[self.__index]
 
582
                self.__editor.textbuffer.place_cursor(begin)
 
583
                self.__editor.textbuffer.apply_tag(self.__selection_tag, begin, end)
 
584
                from SCRIBES.cursor import move_view_to_cursor
 
585
                move_view_to_cursor(self.__editor.textview)
 
586
                if self.__status_id:
 
587
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
588
                from i18n import msg0003
 
589
                message = msg0003 % (self.__index+1, self.__number_of_matches)
 
590
                self.__status_id = self.__editor.feedback.set_modal_message(message, "find")
 
591
                return
 
592
 
 
593
        def __search_cancel_cb(self, SearchReplaceManager):
 
594
                """
 
595
                Handles callback when the "cancel" signal is emitted.
 
596
 
 
597
                @param self: Reference to the SearchReplaceManager instance.
 
598
                @type self: A SearchReplaceManager object.
 
599
 
 
600
                @param SearchReplaceManager: The text editor's SearchReplaceManager.
 
601
                @type SearchReplaceManager: A SearchReplaceManager object.
 
602
                """
 
603
                self.__cancel_search_operation = True
 
604
                self.__cancel_replace_operation = True
 
605
                self.__reset()
 
606
                from i18n import msg0006
 
607
                self.__editor.feedback.set_modal_message(msg0006, "stop")
 
608
                return
 
609
 
 
610
        def __search_hide_bar_cb(self, editor, bar):
 
611
                """
 
612
                Handles callback when the "hide-bar" signal is emitted.
 
613
 
 
614
                @param self: Reference to the SearchReplaceManager instance.
 
615
                @type self: A SearchReplaceManager object.
 
616
 
 
617
                @param editor: Reference to the text editor.
 
618
                @type editor: An Editor object.
 
619
 
 
620
                @param bar: One of the text editor's bar objects.
 
621
                @type bar: A ScribesBar object.
 
622
                """
 
623
                from operator import is_, truth
 
624
                if truth(self.__start_point_mark) and is_(self.__start_point_mark.get_deleted(), False):
 
625
                        self.__editor.textbuffer.delete_mark(self.__start_point_mark)
 
626
                        self.__start_point_mark = None
 
627
                if truth(self.__end_point_mark) and is_(self.__end_point_mark.get_deleted(), False):
 
628
                        self.__editor.textbuffer.delete_mark(self.__end_point_mark)
 
629
                        self.__end_point_mark = None
 
630
                self.__bar_is_visible = False
 
631
                if not self.__index is None:
 
632
                        begin, end = self.__position_of_matches[self.__index]
 
633
                        self.__editor.textbuffer.select_range(begin, end)
 
634
                self.__reset()
 
635
                self.__enable_regular_expression = False
 
636
                self.__enable_incremental_search = False
 
637
                return
 
638
 
 
639
        def __search_show_bar_cb(self, editor, bar):
 
640
                """
 
641
                Handles callback when the "show-bar" signal is emitted.
 
642
 
 
643
                @param self: Reference to the SearchReplaceManager instance.
 
644
                @type self: A SearchReplaceManager object.
 
645
 
 
646
                @param editor: Reference to the text editor.
 
647
                @type editor: An Editor object.
 
648
 
 
649
                @param bar: One of the text editor's bar objects.
 
650
                @type bar: A ScribesBar object.
 
651
                """
 
652
                self.__bar_is_visible = True
 
653
                return
 
654
 
 
655
        def __search_replacing_cb(self, processor):
 
656
                self.__reset_flag = False
 
657
                from i18n import msg0007
 
658
                if self.__status_id:
 
659
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
660
                self.__status_id = self.__editor.feedback.set_modal_message(msg0007, "run")
 
661
                return
 
662
 
 
663
        def __search_replaced_cb(self, processor):
 
664
                self.__reset_flag = False
 
665
                from i18n import msg0008
 
666
                if self.__status_id:
 
667
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
668
                self.__editor.feedback.update_status_message(msg0008, "succeed", 10)
 
669
                return
 
670
 
 
671
        def __search_replace_all_cb(self, processor):
 
672
                self.__reset_flag = False
 
673
                from i18n import msg0009
 
674
                if self.__status_id:
 
675
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
676
                self.__editor.feedback.update_status_message(msg0009, "succeed", 10)
 
677
                return
 
678
 
 
679
        def __search_client_cb(self, client, cnxn_id, entry, data):
 
680
                """
 
681
                Handles callback when the GConf database is modified.
 
682
 
 
683
                @param self: Reference to the SearchReplaceManager instance.
 
684
                @type self: A SearchReplaceManager object.
 
685
                """
 
686
                self.__match_case = client.get_bool("/apps/scribes/match_case")
 
687
                self.__match_word = client.get_bool("/apps/scribes/match_word")
 
688
                return
 
689
 
 
690
########################################################################
 
691
#
 
692
#                                               Auxiliary Method
 
693
#
 
694
########################################################################
 
695
 
 
696
        def __reset(self):
 
697
                """
 
698
                Reset the search processor's state.
 
699
 
 
700
                @param self: Reference to the SearchReplaceManager instance.
 
701
                @type self: A SearchReplaceManager object.
 
702
                """
 
703
                if self.__reset_flag:
 
704
                        return
 
705
                if self.__status_id:
 
706
                        self.__editor.feedback.unset_modal_message(self.__status_id)
 
707
                self.__status_id = None
 
708
                self.__index = None
 
709
                self.__number_of_matches = None
 
710
                self.__position_of_matches = []
 
711
                begin, end = self.__editor.textbuffer.get_bounds()
 
712
                self.__editor.textbuffer.remove_tag(self.__match_tag, begin, end)
 
713
                self.__editor.textbuffer.remove_tag(self.__selection_tag, begin, end)
 
714
                self.__editor.textbuffer.remove_tag(self.__replace_tag, begin, end)
 
715
                self.__cancel_search_operation = False
 
716
                self.__cancel_replace_operation = False
 
717
                self.__reset_flag = True
 
718
                return
 
719
 
 
720
        def __destroy_cb(self, manager):
 
721
                """
 
722
                Handles callback when the "destroy" signal is emitted.
 
723
 
 
724
                @param self: Reference to the SearchReplaceManager instance.
 
725
                @type self: A SearchReplaceManager object.
 
726
 
 
727
                @param manager: Reference to the SearchReplaceManager instance.
 
728
                @type manager: A SearchReplaceManager object.
 
729
                """
 
730
                self.__editor.store.remove_object("SearchReplaceManager", self.__store_id)
 
731
                from SCRIBES.utils import disconnect_signal, delete_attributes
 
732
                from SCRIBES.utils import delete_list
 
733
                disconnect_signal(self.__signal_id_1, self)
 
734
                disconnect_signal(self.__signal_id_2, self)
 
735
                disconnect_signal(self.__signal_id_3, self)
 
736
                disconnect_signal(self.__signal_id_4, self)
 
737
                disconnect_signal(self.__signal_id_5, self)
 
738
                disconnect_signal(self.__signal_id_6, self)
 
739
                disconnect_signal(self.__signal_id_7, self)
 
740
                disconnect_signal(self.__signal_id_8, self)
 
741
                disconnect_signal(self.__signal_id_9, self)
 
742
                disconnect_signal(self.__signal_id_12, self)
 
743
                disconnect_signal(self.__signal_id_11, self.__editor)
 
744
                disconnect_signal(self.__signal_id_10, self.__editor)
 
745
                delete_list(self.__queries)
 
746
                delete_list(self.__position_of_matches)
 
747
                delete_attributes(self)
 
748
                del self
 
749
                self = None
 
750
                return