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

neditor.lm.ListMenuClass.character_rename()   A

Complexity

Conditions 1

Size

Total Lines 15
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 5
dl 0
loc 15
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python3
2 1
import os
3 1
import shutil
4 1
import tkinter as tk
5 1
import tkinter.ttk as ttk
6 1
import tkinter.filedialog as filedialog
7 1
import tkinter.messagebox as messagebox
8 1
import xml.etree.ElementTree as ET
9
10 1
from PIL import Image, ImageTk
11
12 1
from . import fm
13
14
15 1
class ListMenuClass():
16
    """リストメニューバーのクラス.
17
18
    ・リストメニューバーにあるプログラム群
19
20
    Args:
21
        app (instance): MainProcessingClass のインスタンス
22
        master (instance): toplevel のインスタンス
23
        TREE_FOLDER (list): ツリーフォルダの配列
24
    """
25 1
    text_text = ""
26
    """現在入力中の初期テキスト."""
27 1
    select_list_item = ""
28
    """選択中のリストボックスアイテム名."""
29
30 1
    def __init__(self, app, master, TREE_FOLDER):
31 1
        self.app = app
32 1
        self.master = master
33 1
        self.TREE_FOLDER = TREE_FOLDER
34
35 1
    def message_window(self, event=None):
36
        """ツリービューを右クリックしたときの処理.
37
38
        ・子アイテムならば削除ダイアログを表示する。
39
        親アイテムならば追加を行う。
40
41
        Args:
42
            event (instance): tkinter.Event のインスタンス
43
        """
44
        # 選択アイテムの認識番号取得
45 1
        curItem = self.app.tree.focus()
46
        # 親アイテムの認識番号取得
47 1
        parentItem = self.app.tree.parent(curItem)
48
        # 親アイテムをクリックしたとき
49 1
        if self.app.tree.item(curItem)["text"] == self.TREE_FOLDER[4][1]:
50
            # イメージアイテムの親アイテムを選択したとき
51 1
            self.check_image_true()
52
        else:
53 1
            if (
54
                        str(self.app.tree.item(curItem)["text"])
55
                    ) and (
56
                        not str(self.app.tree.item(parentItem)["text"])
57
                    ):
58
                # イメージアイテム以外の親アイテムを選択したとき
59 1
                self.check_image_false(curItem)
60
            else:
61
                # 子アイテムを右クリックしたとき
62 1
                self.click_child_item(curItem, parentItem)
63
64 1
    def on_name_click(self, event=None):
65
        """名前の変更.
66
67
        ・リストボックスの名前を変更する。
68
69
        Args:
70
            event (instance): tkinter.Event のインスタンス
71
        """
72
        # 開いているファイルを保存
73 1
        self.app.fmc.open_file_save(fm.FileMenuClass.now_path)
74
        # 選択アイテムの認識番号取得
75 1
        curItem = self.app.tree.focus()
76
        # 親アイテムの認識番号取得
77 1
        parentItem = self.app.tree.parent(curItem)
78 1
        text = self.app.tree.item(parentItem)["text"]
79 1
        if not text == "":
80 1
            old_file = self.app.tree.item(curItem)["text"]
81 1
            title = self.app.dic.get_dict("Rename {0}").format(old_file)
82 1
            dialog2 = MyDialogClass(
83
                self.app,
84
                self.app.dic.get_dict("Change"),
85
                True,
86
                title,
87
                old_file
88
            )
89 1
            self.master.wait_window(dialog2.sub_name_win)
90
            # テキストを読み取り専用を解除する
91 1
            self.app.text.configure(state='normal')
92 1
            new_file = dialog2.txt
93 1
            del dialog2
94 1
            for val in self.TREE_FOLDER:
95 1
                if text == val[1]:
96 1
                    path1 = "./{0}/{1}.txt".format(val[0], old_file)
97 1
                    path2 = "./{0}/{1}.txt".format(val[0], new_file)
98 1
                    fm.FileMenuClass.now_path = path2
99
                    # テキストの名前を変更する
100 1
                    os.rename(path1, path2)
101 1
                    self.app.tree.delete(curItem)
102 1
                    Item = self.app.tree.insert(
103
                        parentItem,
104
                        'end',
105
                        text=new_file
106
                    )
107 1
                    if val == self.TREE_FOLDER[0]:
108 1
                        self.character_rename(
109
                            fm.FileMenuClass.now_path,
110
                            val[0],
111
                            old_file,
112
                            new_file
113
                        )
114
115 1
                    if val == self.TREE_FOLDER[4]:
116 1
                        self.rename_gif(val[0], old_file, new_file)
117
118 1
                    self.app.tree.selection_set(Item)
119 1
                    self.path_read_text(val[0], new_file)
120 1
                    return
121
122 1
    def character_rename(self, now_path, folder, old_file, new_file):
123
        """キャラクターの名前変更.
124
125
        ・キャラクターの名前を変更する。
126
127
        Args:
128
            now_path (str): 今の処理ししているファイルのパス
129
            folder (str): 今処理しているフォルダ
130
            old_file (str): 変更前のファイル名
131
            new_file (str): 変更後のファイル名
132
        """
133 1
        self.rename_gif(folder, old_file, new_file)
134 1
        f = open(now_path, 'w', encoding='utf-8')
135 1
        f.write(self.app.fmc.save_charactor_file(new_file))
136 1
        f.close()
137
138 1
    @staticmethod
139
    def rename_gif(folder, old_file, new_file):
140
        """gifの名前変更.
141
142
        ・gifの名前を変更する。
143
144
        Args:
145
            folder (str): 今処理しているフォルダ
146
            old_file (str): 変更前のファイル名
147
            new_file (str): 変更後のファイル名
148
        """
149 1
        path1 = "./{0}/{1}.gif".format(folder, old_file)
150 1
        path2 = "./{0}/{1}.gif".format(folder, new_file)
151 1
        if os.path.isfile(path1):
152 1
            os.rename(path1, path2)
153
154 1
    def path_read_image(self, image_path, image_name, scale):
155
        """イメージを読み込んで表示.
156
157
        ・パスが存在すればイメージファイルを読み込んで表示する。
158
159
        Args:
160
            image_path (str): イメージファイルの相対パス
161
            image_name (str): イメージファイルの名前
162
            scale (int): 拡大率(%)
163
        """
164 1
        if not fm.FileMenuClass.now_path == "":
165 1
            title = "{0}/{1}.gif".format(
166
                image_path,
167
                image_name
168
            )
169 1
            giffile = Image.open(title)
170 1
            if scale > 0:
171 1
                giffile = giffile.resize(
172
                    (
173
                        int(giffile.width / 100*scale),
174
                        int(giffile.height / 100*scale)
175
                    ),
176
                    resample=Image.LANCZOS
177
                )
178
179 1
            self.app.image_space.photo = ImageTk.PhotoImage(giffile)
180 1
            self.app.image_space.itemconfig(
181
                self.app.image_on_space,
182
                image=self.app.image_space.photo
183
            )
184
            # イメージサイズにキャンバスサイズを合わす
185 1
            self.app.image_space.config(
186
                scrollregion=(
187
                    0,
188
                    0,
189
                    giffile.size[0],
190
                    giffile.size[1]
191
                )
192
            )
193 1
            giffile.close()
194
195 1
        self.app.winfo_toplevel().title(
196
                self.app.dic.get_dict(
197
                    "Novel Editor/{0}/{1}"
198
                ).format(self.TREE_FOLDER[4][1], image_name)
199
            )
200
201 1
    def path_read_text(self, text_path, text_name):
202
        """テキストを読み込んで表示.
203
204
        ・パスが存在すればテキストを読み込んで表示する。
205
206
        Args:
207
            text_path (str): テキストファイルの相対パス
208
            text_name (str): テキストファイルの名前
209
        """
210 1
        if not fm.FileMenuClass.now_path == "":
211 1
            if not fm.FileMenuClass.now_path.find(
212
                        self.TREE_FOLDER[0][0]
213
                    ) == -1:
214 1
                self.app.txt_yobi_name.configure(state='normal')
215 1
                self.app.txt_yobi_name.delete('0', tk.END)
216 1
                self.app.txt_name.delete('0', tk.END)
217 1
                self.app.txt_birthday.delete('0', tk.END)
218 1
                self.app.text_body.delete('1.0', tk.END)
219 1
                tree = ET.parse(fm.FileMenuClass.now_path)
220 1
                elem = tree.getroot()
221 1
                self.app.txt_yobi_name.insert(tk.END, elem.findtext("call"))
222 1
                self.app.txt_yobi_name.configure(state='readonly')
223 1
                self.app.txt_name.insert(tk.END, elem.findtext("name"))
224 1
                self.app.var.set(elem.findtext("sex"))
225 1
                self.app.txt_birthday.insert(tk.END, elem.findtext("birthday"))
226 1
                self.app.text_body.insert(tk.END, elem.findtext("body"))
227 1
                title = "{0}/{1}.gif".format(
228
                    self.TREE_FOLDER[0][0],
229
                    elem.findtext("call")
230
                )
231 1
                if os.path.isfile(title):
232 1
                    self.app.spc.print_gif(title)
233
            else:
234 1
                self.app.text.delete('1.0', tk.END)
235 1
                f = open(fm.FileMenuClass.now_path, 'r', encoding='utf-8')
236 1
                self.text_text_input(f.read())
237 1
                self.app.text.insert(tk.END, self.text_text)
238 1
                f.close()
239
240 1
            self.app.winfo_toplevel().title(
241
                self.app.dic.get_dict(
242
                    "Novel Editor/{0}/{1}"
243
                ).format(text_path, text_name)
244
            )
245
            # シンタックスハイライトをする
246 1
            self.app.hpc.all_highlight()
247
248 1
    def on_double_click(self, event=None):
249
        """ツリービューをダブルクリック.
250
251
        ・ファイルを保存して閉じて、選択されたアイテムを表示する。
252
253
        Args:
254
            event (instance): tkinter.Event のインスタンス
255
        """
256
        # 選択アイテムの認識番号取得
257 1
        curItem = self.app.tree.focus()
258
        # 親アイテムの認識番号取得
259 1
        parentItem = self.app.tree.parent(curItem)
260 1
        text = self.app.tree.item(parentItem)["text"]
261
        # 開いているファイルを保存
262 1
        self.app.fmc.open_file_save(fm.FileMenuClass.now_path)
263
        # テキストを読み取り専用を解除する
264 1
        self.app.cwc.frame()
265 1
        self.app.text.configure(state='disabled')
266
        # 条件によって分離
267 1
        self.select_list_item_input(self.app.tree.item(curItem)["text"])
268 1
        path = ""
269 1
        for val in self.TREE_FOLDER:
270 1
            if text == val[1]:
271 1
                if val[0] == self.TREE_FOLDER[4][0]:
272 1
                    path = "./{0}/{1}.txt".format(
273
                        val[0],
274
                        self.select_list_item
275
                    )
276 1
                    f = open(path, 'r', encoding='utf-8')
277 1
                    zoom = f.read()
278 1
                    self.app.spc.zoom = int(zoom)
279 1
                    fm.FileMenuClass.now_path = path
280 1
                    self.app.cwc.frame_image()
281 1
                    self.path_read_image(
282
                        self.TREE_FOLDER[4][0],
283
                        self.select_list_item,
284
                        self.app.spc.zoom
285
                    )
286
                else:
287 1
                    path = "./{0}/{1}.txt".format(
288
                        val[0],
289
                        self.select_list_item
290
                    )
291 1
                    fm.FileMenuClass.now_path = path
292 1
                    if val[0] == self.TREE_FOLDER[0][0]:
293 1
                        self.app.cwc.frame_character()
294
                    else:
295
                        # テキストを読み取り専用を解除する
296 1
                        self.app.text.configure(state='normal')
297 1
                        self.app.text.focus()
298
299 1
                    self.path_read_text(text, self.select_list_item)
300
301 1
                return
302
303 1
        fm.FileMenuClass.now_path = ""
304 1
        self.app.winfo_toplevel().title(
305
            self.app.dic.get_dict("Novel Editor")
306
        )
307
308 1
    def check_image_true(self):
309
        """イメージアイテムを右クリックしたとき.
310
311
        ・イメージアイテムの親アイテムを右クリックしたときの処理。
312
        """
313
        # イメージアイテムを選択したとき
314 1
        fTyp = [(self.app.dic.get_dict("Novel Editor"), '*.gif')]
315 1
        iDir = os.path.abspath(os.path.dirname(__file__))
316 1
        filepath = filedialog.askopenfilename(
317
            filetypes=fTyp,
318
            initialdir=iDir
319
        )
320
        # ファイル名があるとき
321 1
        if not filepath == "":
322 1
            file_name = os.path.splitext(os.path.basename(filepath))[0]
323 1
            path = "./{0}/{1}.gif".format(
324
                self.TREE_FOLDER[4][0],
325
                file_name
326
            )
327 1
            shutil.copy2(filepath, path)
328 1
            self.app.cwc.frame_image()
329 1
            path = "./{0}/{1}.txt".format(
330
                self.TREE_FOLDER[4][0],
331
                file_name
332
            )
333 1
            tree = self.app.tree.insert(
334
                self.TREE_FOLDER[4][0],
335
                'end',
336
                text=file_name
337
            )
338 1
            self.app.tree.see(tree)
339 1
            self.app.tree.selection_set(tree)
340 1
            self.app.tree.focus(tree)
341 1
            self.select_list_item_input(file_name)
342 1
            fm.FileMenuClass.now_path = path
343 1
            f = open(path, 'w', encoding='utf-8')
344 1
            self.app.spc.zoom = 100
345 1
            f.write(str(self.app.spc.zoom))
346 1
            f.close()
347 1
            self.app.cwc.frame_image()
348 1
            self.path_read_image(
349
                self.TREE_FOLDER[4][0],
350
                file_name,
351
                0
352
            )
353
354 1
    def check_image_false(self, curItem):
355
        """イメージアイテム以外を右クリックしたとき.
356
357
        ・イメージアイテム以外の親アイテムを右クリックしたときの処理。
358
359
        Args:
360
            curItem (int): 選択アイテムの認識番号
361
        """
362
        # サブダイヤログを表示する
363 1
        title = self.app.dic.get_dict(
364
            "Insert in {0}"
365
        ).format(self.app.tree.item(curItem)["text"])
366 1
        dialog = MyDialogClass(
367
            self.app,
368
            self.app.dic.get_dict("Insert"),
369
            True,
370
            title,
371
            False
372
        )
373 1
        self.master.wait_window(dialog.sub_name_win)
374 1
        file_name = dialog.txt
375 1
        del dialog
376 1
        if not file_name == "":
377 1
            self.app.fmc.open_file_save(fm.FileMenuClass.now_path)
378 1
            curItem = self.app.tree.focus()
379 1
            text = self.app.tree.item(curItem)["text"]
380 1
            path = ""
381 1
            tree = ""
382
            # 選択されているフォルダを見つける
383 1
            for val in self.TREE_FOLDER:
384 1
                if text == val[1]:
385 1
                    if val[0] == self.TREE_FOLDER[0][0]:
386 1
                        self.app.cwc.frame_character()
387 1
                        self.app.txt_yobi_name.configure(state='normal')
388 1
                        self.app.txt_yobi_name.insert(
389
                            tk.END,
390
                            file_name
391
                        )
392 1
                        self.app.txt_yobi_name.configure(state='readonly')
393
                    else:
394
                        self.app.cwc.frame()
395
396 1
                    path = "./{0}/{1}.txt".format(val[0], file_name)
397 1
                    tree = self.app.tree.insert(
398
                        val[0],
399
                        'end',
400
                        text=file_name
401
                    )
402 1
                    fm.FileMenuClass.now_path = path
403 1
                    break
404
405
            # パスが存在すれば新規作成する
406 1
            if not path == "":
407 1
                f = open(path, 'w', encoding='utf-8')
408 1
                f.write("")
409 1
                f.close()
410
                # ツリービューを選択状態にする
411 1
                self.app.tree.see(tree)
412 1
                self.app.tree.selection_set(tree)
413 1
                self.app.tree.focus(tree)
414 1
                self.select_list_item_input(file_name)
415 1
                self.app.winfo_toplevel().title(
416
                    self.app.dic.get_dict(
417
                        "Novel Editor/{0}/{1}"
418
                    ).format(text, file_name)
419
                )
420 1
                self.app.text.focus()
421
                # テキストを読み取り専用を解除する
422 1
                self.app.text.configure(state='normal')
423 1
                self.app.hpc.create_tags()
424
425 1
    def click_child_item(self, curItem, parentItem):
426
        """子アイテムを右クリックしたとき.
427
428
        ・子アイテムを右クリックしたときの処理。
429
430
        Args:
431
            curItem (int): 選択アイテムの認識番号
432
            parentItem (int): 親アイテムの認識番号
433
        """
434 1
        if str(self.app.tree.item(curItem)["text"]):
435
            # 項目を削除する
436 1
            file_name = self.app.tree.item(curItem)["text"]
437 1
            text = self.app.tree.item(parentItem)["text"]
438
            # OK、キャンセルダイアログを表示し、OKを押したとき
439 1
            if messagebox.askokcancel(
440
                    self.app.dic.get_dict("Delete item"),
441
                    self.app.dic.get_dict(
442
                        "Delete {0} item?"
443
                    ).format(file_name)
444
            ):
445 1
                image_path = ""
446 1
                path = ""
447
                # パスを取得する
448 1
                for val in self.TREE_FOLDER:
449 1
                    if text == val[1]:
450 1
                        path = "./{0}/{1}.txt".format(
451
                            val[0],
452
                            file_name
453
                        )
454 1
                        image_path = "./{0}/{1}.gif".format(
455
                            val[0],
456
                            file_name
457
                        )
458 1
                        self.app.tree.delete(curItem)
459 1
                        fm.FileMenuClass.now_path = ""
460 1
                        break
461
                # imageパスが存在したとき
462 1
                if os.path.isfile(image_path):
463 1
                    os.remove(image_path)
464
465
                # パスが存在したとき
466 1
                if not path == "":
467 1
                    os.remove(path)
468 1
                    self.app.cwc.frame()
469 1
                    self.app.text.focus()
470
471 1
    @classmethod
472
    def text_text_input(cls, text_text):
473
        """現在入力中の初期テキストを入力.
474
475
        ・現在入力中の初期テキストをクラス変数に入力する。
476
477
        Args:
478
            text_text (str): 現在入力中の初期テキスト
479
        """
480 1
        cls.text_text = text_text
481
482 1
    @classmethod
483
    def select_list_item_input(cls, select_list_item):
484
        """選択中のリストボックスアイテム名を入力.
485
486
        ・選択中のリストボックスアイテム名をクラス変数に入力する。
487
488
        Args:
489
            select_list_item (str): 選択中のリストボックスアイテム名
490
        """
491 1
        cls.select_list_item = select_list_item
492
493
494 1
class MyDialogClass():
495
    """ダイアログ作成クラス.
496
497
    ・自作ダイアログを呼び出し表示する。
498
499
    Args:
500
        app (instance): 親ウインドウインスタンス
501
        caption (str): ボタンのメッセージ
502
        cancel (bool): キャンセルボタンを表示する(True)
503
        title (str): タイトル
504
        text (bool): 選択状態にする(True)
505
    """
506 1
    def __init__(self, app, caption, cancel, title, text):
507 1
        self.txt = ""
508 1
        self.sub_name_win = tk.Toplevel(app)
509 1
        self.txt_name = ttk.Entry(self.sub_name_win, width=40)
510 1
        self.txt_name.grid(
511
            row=0,
512
            column=0,
513
            columnspan=2,
514
            padx=5,
515
            pady=5,
516
            sticky=tk.W+tk.E,
517
            ipady=3
518
        )
519 1
        button = ttk.Button(
520
            self.sub_name_win,
521
            text=caption,
522
            width=str(caption),
523
            padding=(10, 5),
524
            command=self.sub_name_ok
525
        )
526 1
        button.grid(row=1, column=0)
527 1
        if cancel:
528 1
            button2 = ttk.Button(
529
                self.sub_name_win,
530
                text=app.dic.get_dict("Cancel"),
531
                width=str(app.dic.get_dict("Cancel")),
532
                padding=(10, 5),
533
                command=self.sub_name_win.destroy
534
            )
535
536 1
            button2.grid(row=1, column=1)
537 1
            self.txt_name.focus()
538 1
            if text is not False:
539 1
                self.txt_name.insert(tk.END, text)
540 1
                self.txt_name.select_range(0, 'end')
541
542 1
        self.sub_name_win.title(title)
543 1
        self.txt_name.focus()
544
545 1
    def sub_name_ok(self, event=None):
546
        """ダイアログボタンクリック時の処理.
547
548
        ・自作ダイアログのボタンをクリックしたときにインプットボックスに
549
        入力されている値を取得する。
550
551
        Args:
552
            event (instance): tkinter.Event のインスタンス
553
554
        Returns:
555
            str: インプットボックスの値
556
        """
557 1
        self.txt = self.txt_name.get()
558 1
        self.sub_name_win.destroy()
559
        return self.txt
560