Test Failed
Push — master ( 705b0f...728f1f )
by Yoshihiro
03:24
created

neditor.lm   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 458
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 281
dl 0
loc 458
rs 9.28
c 0
b 0
f 0
wmc 39

10 Methods

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