NovelEditor.ListMenuClass.ListMenuClass.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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