mirror of
https://github.com/ocogeclub/ocoge.git
synced 2024-11-21 15:19:48 +00:00
[update] pybfm.py を TkinterDnD2 がなくても起動するよう変更
This commit is contained in:
parent
36c3497492
commit
e92fbfc6ed
4
.gitignore
vendored
4
.gitignore
vendored
@ -6,5 +6,7 @@ build/
|
||||
*.bak
|
||||
*.old
|
||||
|
||||
out/
|
||||
|
||||
out/
|
||||
.mypy_cache
|
||||
tkinterdnd2
|
Binary file not shown.
437
lib/pybfm.py
437
lib/pybfm.py
@ -1,215 +1,224 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from tkinter import *
|
||||
from tkinterdnd2 import *
|
||||
import os
|
||||
import sys
|
||||
import pyboard
|
||||
import serial.tools.list_ports
|
||||
from tkinter import filedialog
|
||||
|
||||
##### 引数 #####
|
||||
args = sys.argv
|
||||
try:
|
||||
dev = args[1]
|
||||
except IndexError as err:
|
||||
dev = False
|
||||
else:
|
||||
dev = (dev=='-f')
|
||||
|
||||
##### グローバル変数 #####
|
||||
gport = None
|
||||
|
||||
##### イベントハンドラ #####
|
||||
# リストボックスにドロップ
|
||||
def listbox_drop(event):
|
||||
files = listbox.tk.splitlist(event.data)
|
||||
putfiles(files)
|
||||
# キーボード
|
||||
def input_key(ev):
|
||||
if ev.keysym == 'F5':
|
||||
reload()
|
||||
elif ev.keysym == 'Delete':
|
||||
rmfiles()
|
||||
# ダブルクリック
|
||||
def dbl_click(ev):
|
||||
run()
|
||||
# 右クリックメニュー
|
||||
def pop_menu(ev):
|
||||
listbox.select_clear(0, END)
|
||||
listbox.select_set(listbox.nearest(ev.y))
|
||||
pmenu.post(ev.x_root, ev.y_root)
|
||||
|
||||
##### pyboard関数 #####
|
||||
# 接続・repl開始
|
||||
def connect():
|
||||
global gport
|
||||
try:
|
||||
pyb = pyboard.Pyboard(gport)
|
||||
except pyboard.PyboardError as err:
|
||||
gport = None
|
||||
listbox.delete(0, END)
|
||||
set_title('Lost device : Please reload')
|
||||
raise pyboard.PyboardError('Lost device')
|
||||
pyb.enter_raw_repl(False)
|
||||
return pyb
|
||||
# repl終了・切断
|
||||
def disconnect(pyb):
|
||||
try:
|
||||
pyb.exit_raw_repl()
|
||||
except Exception as err:
|
||||
pass
|
||||
try:
|
||||
pyb.close()
|
||||
except Exception as err:
|
||||
pass
|
||||
# ファイル送信 (複数可)(files: list of local filepath)
|
||||
def putfiles(files):
|
||||
pyb = connect()
|
||||
for src in files:
|
||||
if os.path.exists(src):
|
||||
if os.path.isfile(src):
|
||||
dest = os.path.basename(src)
|
||||
print('ファイル "%s" を転送' % src)
|
||||
pyb.fs_put(src, dest)
|
||||
else:
|
||||
print('フォルダは転送できません : %s' % src)
|
||||
else:
|
||||
print('ファイル "%s" は見つかりません。' % f)
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# ポートスキャン:アルファベット順で一番若いポートを返す
|
||||
def find_device():
|
||||
global gport
|
||||
for p in sorted(serial.tools.list_ports.comports()):
|
||||
if p.hwid.startswith('USB'):
|
||||
gport = p.device
|
||||
set_title(gport)
|
||||
break
|
||||
else:
|
||||
gport = None
|
||||
set_title('No device')
|
||||
raise OSError('Device not found')
|
||||
# 再読込:ここのみデバイスの再スキャンが入る
|
||||
def reload():
|
||||
if not gport:
|
||||
find_device()
|
||||
if gport:
|
||||
listfiles()
|
||||
# ファイルリスト取得だけを行う
|
||||
def listfiles():
|
||||
pyb = connect()
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# ファイルリストを取得し、リストボックスに表示 (pyb: pyboard handle, src: target directory on device)
|
||||
def ls(pyb, src='/'):
|
||||
cmd = (
|
||||
"import uos\nfor f in uos.listdir(%s):\n"
|
||||
" print(f)"
|
||||
% (("'%s'" % src) if src else "")
|
||||
)
|
||||
retval = pyb.exec(cmd)
|
||||
files = retval.decode('utf-8').splitlines()
|
||||
listbox.delete(0, END)
|
||||
for f in files:
|
||||
listbox.insert(END, f)
|
||||
# ウィンドウタイトル (title: string)
|
||||
def set_title(title):
|
||||
root.title('PyBfm - ' + title)
|
||||
# デバイス上のファイルを実行
|
||||
def run(follow=False):
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
src = listbox.get(selected[0])
|
||||
ext = os.path.splitext(src)[1]
|
||||
if ext == '.py':
|
||||
cmd = 'exec(open("%s").read())' % src
|
||||
pyb = connect()
|
||||
try:
|
||||
if follow:
|
||||
print (pyb.exec(cmd).decode('utf-8'))
|
||||
else:
|
||||
pyb.exec_raw_no_follow(cmd)
|
||||
except Exception as err:
|
||||
print("Runtime error.")
|
||||
print('Done.')
|
||||
disconnect(pyb)
|
||||
else:
|
||||
print('このファイルは実行できません')
|
||||
# ファイル選択ダイアログからファイル送信
|
||||
def putdlg():
|
||||
fpath = filedialog.askopenfilename()
|
||||
if fpath:
|
||||
putfiles([fpath])
|
||||
# ファイル受信
|
||||
def getfile():
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
src = listbox.get(selected[0])
|
||||
ext = os.path.splitext(src)[1]
|
||||
dest = filedialog.asksaveasfilename(
|
||||
initialfile=src,
|
||||
defaultextension=ext,
|
||||
filetypes=[('変更なし', ext), ('全てのファイル', '.*')]
|
||||
)
|
||||
if dest:
|
||||
pyb = connect()
|
||||
pyb.fs_get(src, dest)
|
||||
disconnect(pyb)
|
||||
# デバイス上のファイル削除(複数可)
|
||||
def rmfiles():
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
pyb = connect()
|
||||
for i in selected:
|
||||
src = listbox.get(i)
|
||||
pyb.fs_rm(src)
|
||||
print('Deleted %s' % src)
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# 何もしない関数
|
||||
def do_nothing():
|
||||
pass
|
||||
|
||||
##### メイン #####
|
||||
|
||||
# メインウィンドウの生成
|
||||
root = TkinterDnD.Tk()
|
||||
root.title('PyBfm')
|
||||
root.geometry('400x300')
|
||||
pmenu = Menu(root, tearoff=0)
|
||||
pmenu.add_command(label="実行", command=run)
|
||||
if dev:
|
||||
pmenu.add_command(label="実行 (追跡)", command=lambda:run(True))
|
||||
pmenu.add_command(label="送る", command=putdlg)
|
||||
pmenu.add_command(label="取得", command=getfile)
|
||||
pmenu.add_command(label="削除", command=rmfiles)
|
||||
pmenu.add_command(label="再読込", command=reload)
|
||||
pmenu.add_command(label="閉じる", command=do_nothing)
|
||||
# root.config(bg='#cccccc')
|
||||
# Frameウィジェットの生成
|
||||
frame = Frame(root)
|
||||
# Listboxウィジェットの生成
|
||||
listbox = Listbox(frame, selectmode=EXTENDED)
|
||||
listbox.drop_target_register(DND_FILES)
|
||||
listbox.dnd_bind('<<Drop>>', listbox_drop)
|
||||
listbox.bind("<KeyPress>", input_key)
|
||||
listbox.bind("<Double-Button-1>", dbl_click)
|
||||
listbox.bind("<Button-3>", pop_menu)
|
||||
# スクロールバーの生成
|
||||
scroll = Scrollbar(frame, orient=VERTICAL)
|
||||
listbox.configure(yscrollcommand=scroll.set)
|
||||
scroll.config(command=listbox.yview)
|
||||
# ウィジェットの配置
|
||||
frame.pack(expand=True,fill=BOTH)
|
||||
listbox.pack(expand=True,fill=BOTH, side=LEFT)
|
||||
scroll.pack(side=RIGHT, fill=Y)
|
||||
|
||||
try:
|
||||
find_device()
|
||||
except Exception as err:
|
||||
pass
|
||||
else:
|
||||
listfiles()
|
||||
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from tkinter import *
|
||||
try:
|
||||
from tkinterdnd2 import *
|
||||
except ImportError:
|
||||
dnd = False
|
||||
else:
|
||||
dnd = True
|
||||
import os
|
||||
import sys
|
||||
import pyboard
|
||||
import serial.tools.list_ports
|
||||
from tkinter import filedialog
|
||||
|
||||
##### 引数 #####
|
||||
args = sys.argv
|
||||
try:
|
||||
dev = args[1]
|
||||
except IndexError as err:
|
||||
dev = False
|
||||
else:
|
||||
dev = (dev=='-f')
|
||||
|
||||
##### グローバル変数 #####
|
||||
gport = None
|
||||
|
||||
##### イベントハンドラ #####
|
||||
# リストボックスにドロップ
|
||||
def listbox_drop(event):
|
||||
files = listbox.tk.splitlist(event.data)
|
||||
putfiles(files)
|
||||
# キーボード
|
||||
def input_key(ev):
|
||||
if ev.keysym == 'F5':
|
||||
reload()
|
||||
elif ev.keysym == 'Delete':
|
||||
rmfiles()
|
||||
# ダブルクリック
|
||||
def dbl_click(ev):
|
||||
run()
|
||||
# 右クリックメニュー
|
||||
def pop_menu(ev):
|
||||
listbox.select_clear(0, END)
|
||||
listbox.select_set(listbox.nearest(ev.y))
|
||||
pmenu.post(ev.x_root, ev.y_root)
|
||||
|
||||
##### pyboard関数 #####
|
||||
# 接続・repl開始
|
||||
def connect():
|
||||
global gport
|
||||
try:
|
||||
pyb = pyboard.Pyboard(gport)
|
||||
except pyboard.PyboardError as err:
|
||||
gport = None
|
||||
listbox.delete(0, END)
|
||||
set_title('Lost device : Please reload')
|
||||
raise pyboard.PyboardError('Lost device')
|
||||
pyb.enter_raw_repl(False)
|
||||
return pyb
|
||||
# repl終了・切断
|
||||
def disconnect(pyb):
|
||||
try:
|
||||
pyb.exit_raw_repl()
|
||||
except Exception as err:
|
||||
pass
|
||||
try:
|
||||
pyb.close()
|
||||
except Exception as err:
|
||||
pass
|
||||
# ファイル送信 (複数可)(files: list of local filepath)
|
||||
def putfiles(files):
|
||||
pyb = connect()
|
||||
for src in files:
|
||||
if os.path.exists(src):
|
||||
if os.path.isfile(src):
|
||||
dest = os.path.basename(src)
|
||||
print('ファイル "%s" を転送' % src)
|
||||
pyb.fs_put(src, dest)
|
||||
else:
|
||||
print('フォルダは転送できません : %s' % src)
|
||||
else:
|
||||
print('ファイル "%s" は見つかりません。' % f)
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# ポートスキャン:アルファベット順で一番若いポートを返す
|
||||
def find_device():
|
||||
global gport
|
||||
for p in sorted(serial.tools.list_ports.comports()):
|
||||
if p.hwid.startswith('USB'):
|
||||
gport = p.device
|
||||
set_title(gport)
|
||||
break
|
||||
else:
|
||||
gport = None
|
||||
set_title('No device')
|
||||
raise OSError('Device not found')
|
||||
# 再読込:ここのみデバイスの再スキャンが入る
|
||||
def reload():
|
||||
if not gport:
|
||||
find_device()
|
||||
if gport:
|
||||
listfiles()
|
||||
# ファイルリスト取得だけを行う
|
||||
def listfiles():
|
||||
pyb = connect()
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# ファイルリストを取得し、リストボックスに表示 (pyb: pyboard handle, src: target directory on device)
|
||||
def ls(pyb, src='/'):
|
||||
cmd = (
|
||||
"import uos\nfor f in uos.listdir(%s):\n"
|
||||
" print(f)"
|
||||
% (("'%s'" % src) if src else "")
|
||||
)
|
||||
retval = pyb.exec(cmd)
|
||||
files = retval.decode('utf-8').splitlines()
|
||||
listbox.delete(0, END)
|
||||
for f in files:
|
||||
listbox.insert(END, f)
|
||||
# ウィンドウタイトル (title: string)
|
||||
def set_title(title):
|
||||
root.title('PyBfm - ' + title)
|
||||
# デバイス上のファイルを実行
|
||||
def run(follow=False):
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
src = listbox.get(selected[0])
|
||||
ext = os.path.splitext(src)[1]
|
||||
if ext == '.py':
|
||||
cmd = 'exec(open("%s").read())' % src
|
||||
pyb = connect()
|
||||
try:
|
||||
if follow:
|
||||
print (pyb.exec(cmd).decode('utf-8'))
|
||||
else:
|
||||
pyb.exec_raw_no_follow(cmd)
|
||||
except Exception as err:
|
||||
print("Runtime error.")
|
||||
print('Done.')
|
||||
disconnect(pyb)
|
||||
else:
|
||||
print('このファイルは実行できません')
|
||||
# ファイル選択ダイアログからファイル送信
|
||||
def putdlg():
|
||||
fpath = filedialog.askopenfilename()
|
||||
if fpath:
|
||||
putfiles([fpath])
|
||||
# ファイル受信
|
||||
def getfile():
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
src = listbox.get(selected[0])
|
||||
ext = os.path.splitext(src)[1]
|
||||
dest = filedialog.asksaveasfilename(
|
||||
initialfile=src,
|
||||
defaultextension=ext,
|
||||
filetypes=[('変更なし', ext), ('全てのファイル', '.*')]
|
||||
)
|
||||
if dest:
|
||||
pyb = connect()
|
||||
pyb.fs_get(src, dest)
|
||||
disconnect(pyb)
|
||||
# デバイス上のファイル削除(複数可)
|
||||
def rmfiles():
|
||||
selected = listbox.curselection()
|
||||
if len(selected):
|
||||
pyb = connect()
|
||||
for i in selected:
|
||||
src = listbox.get(i)
|
||||
pyb.fs_rm(src)
|
||||
print('Deleted %s' % src)
|
||||
ls(pyb)
|
||||
disconnect(pyb)
|
||||
# 何もしない関数
|
||||
def do_nothing():
|
||||
pass
|
||||
|
||||
##### メイン #####
|
||||
|
||||
# メインウィンドウの生成
|
||||
if dnd:
|
||||
root = TkinterDnD.Tk()
|
||||
else:
|
||||
root = Tk()
|
||||
root.title('PyBfm')
|
||||
root.geometry('400x300')
|
||||
pmenu = Menu(root, tearoff=0)
|
||||
pmenu.add_command(label="実行", command=run)
|
||||
if dev:
|
||||
pmenu.add_command(label="実行 (追跡)", command=lambda:run(True))
|
||||
pmenu.add_command(label="送る", command=putdlg)
|
||||
pmenu.add_command(label="取得", command=getfile)
|
||||
pmenu.add_command(label="削除", command=rmfiles)
|
||||
pmenu.add_command(label="再読込", command=reload)
|
||||
pmenu.add_command(label="閉じる", command=do_nothing)
|
||||
# root.config(bg='#cccccc')
|
||||
# Frameウィジェットの生成
|
||||
frame = Frame(root)
|
||||
# Listboxウィジェットの生成
|
||||
listbox = Listbox(frame, selectmode=EXTENDED)
|
||||
if dnd:
|
||||
listbox.drop_target_register(DND_FILES)
|
||||
listbox.dnd_bind('<<Drop>>', listbox_drop)
|
||||
listbox.bind("<KeyPress>", input_key)
|
||||
listbox.bind("<Double-Button-1>", dbl_click)
|
||||
listbox.bind("<Button-3>", pop_menu)
|
||||
# スクロールバーの生成
|
||||
scroll = Scrollbar(frame, orient=VERTICAL)
|
||||
listbox.configure(yscrollcommand=scroll.set)
|
||||
scroll.config(command=listbox.yview)
|
||||
# ウィジェットの配置
|
||||
frame.pack(expand=True,fill=BOTH)
|
||||
listbox.pack(expand=True,fill=BOTH, side=LEFT)
|
||||
scroll.pack(side=RIGHT, fill=Y)
|
||||
|
||||
try:
|
||||
find_device()
|
||||
except Exception as err:
|
||||
pass
|
||||
else:
|
||||
listfiles()
|
||||
|
||||
root.mainloop()
|
Loading…
Reference in New Issue
Block a user