Passed
Push — master ( 1d2121...eed8cd )
by Yoshihiro
02:50
created

neditor.fp.FindProcessingClass.replacement()   A

Complexity

Conditions 4

Size

Total Lines 35
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4.0032

Importance

Changes 0
Metric Value
cc 4
eloc 17
nop 2
dl 0
loc 35
ccs 16
cts 17
cp 0.9412
crap 4.0032
rs 9.55
c 0
b 0
f 0
1
#!/usr/bin/env python3
2 1
import tkinter as tk
3 1
import tkinter.ttk as ttk
4 1
import tkinter.messagebox as messagebox
5
6
7 1
class FindProcessingClass():
8
    """検索置換のクラス.
9
10
    ・検索置換するためのプログラム群
11
12
    Args:
13
        app (instance): MainProcessingClass のインスタンス
14
    """
15 1
    replacement_check = False
16
    """検索ダイアログが表示されているTrue."""
17 1
    next_pos = ""
18
    """次の検索位置 例.(1.0)."""
19 1
    find_text = ""
20
    """検索文字列."""
21
22 1
    def __init__(self, app):
23 1
        self.app = app
24
25 1
    def push_keys(self, event=None):
26
        """キーが押されたときの処理.
27
28
        ・何かキーが押されたときに検索処理を中断する。
29
30
        Args:
31
            event (instance): tkinter.Event のインスタンス
32
        """
33
        # 検索処理を中断する
34 1
        self.replacement_check_input(False)
35
36 1
    def find_dialog(self, event=None):
37
        """検索ダイアログを作成.
38
39
        ・検索ダイアログを作成する。
40
41
        Args:
42
            event (instance): tkinter.Event のインスタンス
43
        """
44 1
        search_win = tk.Toplevel(self.app)
45 1
        self.text_var = ttk.Entry(search_win, width=40)
46 1
        self.text_var.grid(
47
            row=0,
48
            column=0,
49
            columnspan=2,
50
            padx=5,
51
            pady=5,
52
            sticky=tk.W+tk.E,
53
            ipady=3
54
        )
55 1
        button = ttk.Button(
56
            search_win,
57
            text=self.app.dic.get_dict("Find"),
58
            width=str(self.app.dic.get_dict("Find")),
59
            padding=(10, 5),
60
            command=self.search
61
        )
62 1
        button.grid(row=1, column=0)
63 1
        button2 = ttk.Button(
64
            search_win,
65
            text=self.app.dic.get_dict("Asc find"),
66
            width=str(self.app.dic.get_dict("Asc find")),
67
            padding=(10, 5),
68
            command=self.search_forward
69
        )
70 1
        button2.grid(row=1, column=1)
71
        # 最前面に表示し続ける
72 1
        search_win.attributes("-topmost", True)
73 1
        search_win.title(self.app.dic.get_dict("Find"))
74 1
        self.text_var.focus()
75
76 1
    def replacement_dialog(self, event=None):
77
        """置換ダイアログを作成.
78
79
        ・置換ダイアログを作成する。
80
81
        Args:
82
            event (instance): tkinter.Event のインスタンス
83
        """
84 1
        self.replacement_win = tk.Toplevel(self.app)
85 1
        self.text_var = ttk.Entry(self.replacement_win, width=40)
86 1
        self.text_var.grid(
87
            row=0,
88
            column=0,
89
            columnspan=2,
90
            padx=5,
91
            pady=5,
92
            sticky=tk.W+tk.E,
93
            ipady=3
94
        )
95 1
        self.replacement_var = ttk.Entry(self.replacement_win, width=40)
96 1
        self.replacement_var.grid(
97
            row=1,
98
            column=0,
99
            columnspan=2,
100
            padx=5,
101
            pady=5,
102
            sticky=tk.W+tk.E,
103
            ipady=3
104
        )
105 1
        button = ttk.Button(
106
            self.replacement_win,
107
            text=self.app.dic.get_dict("Find"),
108
            width=str(self.app.dic.get_dict("Find")),
109
            padding=(10, 5),
110
            command=self.search
111
        )
112 1
        button.grid(row=2, column=0)
113 1
        button2 = ttk.Button(
114
            self.replacement_win,
115
            text=self.app.dic.get_dict("Replacement"),
116
            width=str(self.app.dic.get_dict("Replacement")),
117
            padding=(10, 5),
118
            command=self.replacement
119
        )
120 1
        button2.grid(row=2, column=1)
121
        # 最前面に表示し続ける
122 1
        self.replacement_win.attributes("-topmost", True)
123 1
        self.replacement_win.title(
124
            self.app.dic.get_dict("Replacement")
125
        )
126 1
        self.text_var.focus()
127
        # ウインドウが閉じられたときの処理
128 1
        self.replacement_win.protocol(
129
            "WM_DELETE_WINDOW",
130
            self.replacement_dialog_on_closing
131
            )
132
133 1
    def replacement_dialog_on_closing(self):
134
        """検索ウインドウが閉じられたときの処理.
135
136
        ・検索ダイアログが閉じられたことがわかるようにする。
137
        """
138 1
        self.replacement_check_input(False)
139 1
        self.replacement_win.destroy()
140
141 1
    def search(self, event=None):
142
        """検索処理.
143
144
        ・検索処理をする。空欄なら処理しない、違うなら最初から、
145
        同じなら次のを検索する。
146
147
        Args:
148
            event (instance): tkinter.Event のインスタンス
149
        """
150
        # 現在選択中の部分を解除
151 1
        self.app.text.tag_remove('sel', '1.0', 'end')
152
153
        # 現在検索ボックスに入力されてる文字
154 1
        now_text = self.text_var.get()
155 1
        if not now_text:
156
            # 空欄だったら処理しない
157
            pass
158 1
        elif now_text != self.find_text:
159
            # 前回の入力と違う文字なら、検索を最初から行う
160 1
            index = '0.0'
161 1
            self.search_next(now_text, index, 0)
162
        else:
163
            # 前回の入力と同じなら、検索の続きを行う
164 1
            self.search_next(now_text, self.next_pos, 1)
165
166
        # 今回の入力を、「前回入力文字」にする
167 1
        self.find_text_input(now_text)
168
169 1
    def replacement(self, event=None):
170
        """置換処理.
171
172
        ・置換処理をする。空欄なら処理しない、違うなら初めから、
173
        同じなら次を検索する。
174
175
        Args:
176
            event (instance): tkinter.Event のインスタンス
177
        """
178
        # 現在選択中の部分を解除
179 1
        self.app.text.tag_remove('sel', '1.0', 'end')
180
181
        # 現在検索ボックスに入力されてる文字
182 1
        now_text = self.text_var.get()
183 1
        replacement_text = self.replacement_var.get()
184 1
        if not now_text or not replacement_text:
185
            # 空欄だったら処理しない
186
            pass
187 1
        elif now_text != self.find_text:
188
            # 前回の入力と違う文字なら、検索を最初から行う
189 1
            self.replacement_check_input(True)
190 1
            index = '0.0'
191 1
            self.search_next(now_text, index, 0)
192
        else:
193
            # 前回の入力と同じなら、検索の続きを行う
194 1
            self.replacement_check_input(True)
195
            # 検索文字の置換を行なう
196 1
            start = self.next_pos
197 1
            end = '{0} + {1}c'.format(self.next_pos, len(now_text))
198 1
            self.app.text.delete(start, end)
199 1
            self.app.text.insert(start, replacement_text)
200 1
            self.search_next(now_text, self.next_pos, 1)
201
202
        # 今回の入力を、「前回入力文字」にする
203 1
        self.find_text_input(now_text)
204
205 1
    def search_forward(self, event=None):
206
        """昇順検索処理.
207
208
        ・昇順検索をする。空欄なら処理しない、違うなら初めから、
209
        同じなら次を検索する。
210
211
        Args:
212
            event (instance): tkinter.Event のインスタンス
213
        """
214
        # 現在選択中の部分を解除
215 1
        self.app.text.tag_remove('sel', '1.0', 'end')
216
217
        # 現在検索ボックスに入力されてる文字
218 1
        text = self.text_var.get()
219 1
        if not text:
220
            # 空欄だったら処理しない
221
            pass
222 1
        elif text != self.find_text:
223
            # 前回の入力と違う文字なら、検索を最初から行う
224 1
            index = 'end'
225 1
            self.search_next(text, index, 2)
226
        else:
227
            # 前回の入力と同じなら、検索の続きを行う
228 1
            self.search_next(text, self.next_pos, 2)
229
230
        # 今回の入力を、「前回入力文字」にする
231 1
        self.find_text_input(text)
232
233 1
    def search_next(self, search, index, case):
234
        """検索のメイン処理.
235
236
        ・検索できれば選択をする。できなければ、ダイアログを出して終了。
237
238
        Args:
239
            search (str): 検索文字列
240
            index (str): 検索位置 ex. (1.0)
241
            case (int): 0.初めから検索 1.次に検索 2.昇順検索
242
        """
243 1
        if case == 2:
244 1
            backwards = True
245 1
            stopindex = '0.0'
246 1
            index = '{0}'.format(index)
247 1
        elif case == 0:
248 1
            backwards = False
249 1
            stopindex = 'end'
250 1
            index = '{0}'.format(index)
251
        else:
252 1
            backwards = False
253 1
            stopindex = 'end'
254 1
            index = '{0} + 1c'.format(index)
255
256 1
        pos = self.app.text.search(
257
            search, index,
258
            stopindex=stopindex,
259
            backwards=backwards
260
        )
261 1
        if not pos:
262 1
            if case == 2:
263 1
                index = "end"
264
            else:
265 1
                index = "0.0"
266
267 1
            pos = self.app.text.search(
268
                search, index,
269
                stopindex=stopindex,
270
                backwards=backwards
271
            )
272 1
            if not pos:
273 1
                messagebox.showinfo(
274
                    "検索",
275
                    "最後まで検索しましたが検索文字はありませんでした。"
276
                )
277 1
                self.replacement_check_input(False)
278 1
                return
279
280 1
        self.next_pos_input(pos)
281 1
        start = pos
282 1
        end = '{0} + {1}c'.format(pos, len(search))
283 1
        self.app.text.tag_add('sel', start, end)
284 1
        self.app.text.mark_set('insert', start)
285 1
        self.app.text.see('insert')
286 1
        self.app.text.focus()
287
288 1
    @classmethod
289
    def replacement_check_input(cls, replacement_check):
290
        """検索ダイアログが表示されているかを入力.
291
292
        ・検索ダイアログが表示されているかを入力する。
293
294
        Args:
295
            replacement_check (bool): 検索ダイアログが表示されているTrue
296
        """
297 1
        cls.replacement_check = replacement_check
298
299 1
    @classmethod
300
    def find_text_input(cls, find_text):
301
        """検索文字を入力.
302
303
        ・検索文字をクラス変数に入力する。
304
305
        Args:
306
            find_text (str): 検索文字
307
        """
308 1
        cls.find_text = find_text
309
310 1
    @classmethod
311
    def next_pos_input(cls, next_pos):
312
        """検索位置を入力.
313
314
        ・検索位置をクラス変数に入力する。
315
316
        Args:
317
            next_pos (str): 検索位置
318
        """
319
        cls.next_pos = next_pos
320