Launcher.Launcher のソースコード

"""
Launcher.py - アプリケーションランチャー

このスクリプトは、様々なアプリケーションやスクリプトを起動するためのGUIランチャーを提供します。
設定ファイル(.ini)からパスや設定を読み込み、ユーザーインターフェースを通じて簡単にプログラムを実行できるようにします。
また、Pythonpathの管理や環境変数の設定も行います。

関連リンク: :doc:`Launcher_usage`
"""
# For future implement: TkinterDnD2: 
#  https://juu7g.hatenablog.com/entry/Python/csv/viewer#%E3%83%89%E3%83%A9%E3%83%83%E3%82%B0%E3%82%A2%E3%83%B3%E3%83%89%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%81%AE%E5%AE%9F%E8%A3%85TkinterDnD2%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9
import os
import sys

v = os.environ.get('tklibPath', None)
if v:
    pythonlib_path = v
else:
    script_path = sys.argv[0]
    tkProg_Root  = os.path.join(script_path, '../../..')
    pythonlib_path  = os.path.abspath(os.path.join(tkProg_Root, 'tklib/python'))

#print(f"Add [{pythonlib_path}] to PYTHONPATH by sys.path.append()")
sys.path.append(pythonlib_path)

import tklib.tkimport as imp

tk = imp.import_lib("tkinter", stop_by_error = False)
imp.messages(stop_by_error = True)

#tkdnd = imp.import_lib("tkinterdnd2", stop_by_error = False)
#numba = imp.import_lib("numba", stop_by_error = False)

from sys import exit
import time
import platform
import glob
import re
from numpy import exp, log, log10, sin, cos, tan, arcsin, arccos, arctan, sqrt
#import tkinter as tk
import tkinter.font as font


from tklib.tkutils import getarg, getintarg, getfloatarg, pint, pfloat, terminate, desktop_name
from tklib.tkutils import get_os, get_last_directory, add_path, split_file_path, find_executable_path, search_executable_path, convert_by_vars
from tklib.tkutils import get_user_inifile_dir
from tklib.tkparams import tkParams
from tklib.tkfile import open_chardet
from tklib.tkgui.tkapplication_gui import tkApplication_GUI
import tklib.tkgui.tktkinter as tktkinter
from tkLauncherApp import tkLauncherApp
from tklib.tkscript_macro import tkScript
from tklib.tksci.tksci import h, h_bar, hbar, e, kB, NA, c, pi, pi2, torad, todeg, basee
from tklib.tksci.tksci import me, mp, mn, u0, e0, e2_4pie0, a0, R, F, g
from tklib.tksci.tksci import acos, asin, atan, cosh, sinh, tanh
from tklib.tksci.tksci import degcos, degsin, degtan, degacos, degasin, degatan
from tklib.tksci.tksci import eVTonm, nmToeV
from tklib.tksci.tksci import factorial, Factorize, Gaussian, Lorentzian, combination, gamma

from tklib.tkgui.tktooltip import tkTooltip


usage_str = "\n" \
          + "(i)   usage: python Launcher.py [-s=script_list_name]\n" \
          + "         ex: python Launcher.py -s={script_list_name}\n"

#=============================
# global variables
#=============================
prog_name = 'Launcher'
version = [1, 4, 0]

#=============================
# Treat argments
#=============================
[ドキュメント] def usage(app): """ 概要: アプリケーションの利用方法を表示します。 詳細説明: アプリケーションの `usage_str` を使用して、コマンドラインでの利用方法をコンソールに出力します。 :param app: tkApplication_GUI: アプリケーションのインスタンス。 """ # cparams = app.get_params() # app.usage(infile = cparams.infile) for s in app.usage_str.split('\n'): cmd = 'print({})'.format(s.rstrip()) eval(cmd)
[ドキュメント] def initialize(app, config): """ 概要: アプリケーションの初期設定とグローバル変数を設定します。 詳細説明: `tkLauncherApp` インスタンスの主要な設定(ウィンドウタイトル、ディレクトリパス、外部アプリケーションパス、GUIの表示設定など)を初期化します。 環境変数もここで設定されます。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 """ #================================ # Global variables #================================ cparams = app.get_params() # 計算エンジンのパラメータオブジェクト tkvars = app.tkvars.get_param_dict() app.window_title = f'{prog_name} {version}' app.cur_sel = 0 app.last_menu = '' app.last_ibutton = 0 app.last_button_type = '' app.last_button_action = '' # tkApplicationで定義済み # app.user = getpass.getuser() # app.user_nospace = self.user.replace(' ', '') # app.argv = sys.argv # app.script_path = sys.argv[0] # app.script_fullpath = os.path.abspath(self.script_path) # app.script_dir = dirname # app.script_filebody = filebody # app.ini_dir = self.get_inifile_dir(use_user_inifile = use_user_inifile, # app.inifile = self.get_inifile_path(self.ini_dir) # dirname, basename, filebody, ext = split_file_path(app.script_fullpath) app.resource_dir = os.path.join(app.script_dir, 'resource') app.extra_scripts = [] app.remove_scripts = [] app.env = os.environ v = app.env.get('tkProg_Root', None) if v: app.tkProg_Root = v else: app.tkProg_Root = os.path.abspath(os.path.join(app.script_dir, '../..')) os_name = platform.system() if os_name == 'Linux': app.use_tooltip = False else: app.use_tooltip = True app.bin_path = os.path.join(app.tkProg_Root, 'bin') app.tklib_Root = os.path.join(app.tkProg_Root, 'tklib') app.pythonlib_path = pythonlib_path app.perllib_path = os.path.join(app.tklib_Root, 'Perl', 'lib') app.tkprog_path = os.path.join(app.tkProg_Root, 'tkprog') app.tkprog_X_path = os.path.abspath(os.path.join(app.script_dir, '..')) if os_name == 'Windows': app.tkapp_path = os.path.join(app.tkProg_Root, 'tkapp_Win') elif os_name == 'Darwin': app.tkapp_path = os.path.join(app.tkProg_Root, 'tkapp_Mac') else: app.tkapp_path = os.path.join(app.tkProg_Root, 'tkapp_Linux') app.tkapp_open_path = os.path.join(app.tkProg_Root, 'tkapp_open') app.tkapp_etc_path = os.path.join(app.tkProg_Root, 'tkapp_etc') app.launcher_script_dir = os.path.join(app.script_dir, 'scripts') app.internal_editor_path = os.path.join(app.tkprog_X_path, 'editor/editor.py') add_path(app.bin_path) """ print("") print(f"OS: {os_name}") print("") print("Directories:") print(" tkProg_Root :", app.tkProg_Root) print(" tklib_Root :", app.tklib_Root) print(" pythonlib_path :", app.pythonlib_path) print(" perllib_path :", app.perllib_path) print(" tkprog_X_path :", app.tkprog_X_path) print(" internal_editor_path:", app.internal_editor_path) print(" tkapp_path :", app.tkapp_path) print(" tkapp_open_path :", app.tkapp_open_path) print(" tkapp_etc_path :", app.tkapp_etc_path) print(" tkprog_path :", app.tkprog_path) print(" launcher_script_dir :", app.launcher_script_dir) """ config.start_path = config.get('start_path', '') if config.start_path == '': files = app.get_start_apps(filename_only = True) if len(files) > 0: config.start_path = files[0] config.shell_path = config.get('shell_path', '') if config.shell_path == '': files = app.get_shells(filename_only = True) if len(files) > 0: config.shell_path = files[0] config.filer_path = config.get('filer_path', '') if config.filer_path == '': files = app.get_filers(filename_only = True) if len(files) > 0: config.filer_path = files[0] config.editor_path = config.get('editor_path', '') if config.editor_path == '': files = app.get_editors(filename_only = True) if len(files) > 0: config.editor_path = files[0] config.python3_path = config.get('python3_path', '') if config.python3_path == '': config.python3_path = search_executable_path(['python3.exe', 'python3', 'python.exe', 'python'], filename_only = True) config.python_path = config.python3_path config.pythonw_path = config.get('pythonw_path', '') if config.pythonw_path == '': config.pythonw_path = search_executable_path(['pythonw.exe', 'pythonw'], filename_only = True) config.perl_path = config.get('perl_path', '') if config.perl_path == '': config.perl_path = search_executable_path(['perl', 'perl.exe'], filename_only = True) config.vesta_path = config.get('vesta_path', '') if config.vesta_path == '': dir = os.path.join(app.tkapp_path, 'VESTA') if os.path.exists(dir): config.vesta_path = os.path.join(dir, 'VESTA') """ print("") print("External applications:") print(" editor_path :", config.editor_path) print(" python_path :", config.python_path) print(" python3_path:", config.python3_path) print(" pythonw_path:", config.pythonw_path) print(" perl_path :", config.perl_path) print(" vesta_path :", config.vesta_path) """ for key in ["tkProg_Root", "tklib_Root", "tklib_path", "pythonlib_path", "perllib_path", "tkprog_X_path", "internal_editor_path", "tkapp_path", "tkapp_open_path", "tkapp_etc_path", "tkprog_path", "script_dir", "script_path", "script_fullpath", "launcher_script_dir"]: app.env[key] = app.get(key, '') # Non-configurable configuration # app.prm_file_type = [('prm file', '*.prm')] # app.data_file_type = [('data file', '*.csv')] # Configurable configuration config = app.config config.lang = 'en' config.debug = False config.print_level = 0 config.confirm_on_exit = False app.show_log = False config.show_log = app.show_log config.minsize = [200, 200] config.geometry = "470x580" config.left_pane_width = 500 if os_name == 'Windows': config.geometry = "470x580" config.default_font_size = 14 config.font_size = 10 config.help_button_font_size = 8 config.path_frame_font_size = 8 config.width_listbox = 40 config.height_listbox = 15 elif os_name == 'Darwin': config.geometry = "470x580" config.default_font_size = 14 config.font_size = 10 config.help_button_font_size = 8 config.path_frame_font_size = 8 config.width_listbox = 40 config.height_listbox = 15 else: config.geometry = "512x664" config.default_font_size = 10 config.font_size = 8 config.help_button_font_size = 6 config.path_frame_font_size = 8 config.width_listbox = 40 config.height_listbox = 12 config.head_label_width = 10 config.width_input_editbox = 80 config.height_input_editbox = 15 config.message_box_width = 40 config.message_box_height = 4 config.width_rbutton = 10 # config.height_rbutton = 7 config.n_tbutton = 5 config.n_rbutton = 7 config.nx_button = 3 config.ny_button = 7 config.n_buttons = config.nx_button * config.ny_button config.width_submenu_button = 18 # config.height_submenu_button = 3 config.width_help_button = 3 config.height_help_button = 1 # Define var types in config for auto type conversion in config.read_parameters() config.editor_path = '' # config.infile = '' # config.outfile = '' # config.score_mode = 'EI' config.program_path = ''
[ドキュメント] def update_vars(app, cparams): """ 概要: コマンドライン引数を解析し、アプリケーションの変数を更新します。 詳細説明: `app.add_argument` を使用して期待されるコマンドライン引数を定義し、`app.read_args` で実際の引数を解析して `cparams` オブジェクトを更新します。 不正な引数があった場合はエラーメッセージを表示し終了します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 """ app.add_argument(opt = "-s", type = "str", var_name = 'script_list_name', opt_str = "-s=script_list_name", desc = 'Script list file', defval = "", optional = True); # app.add_argument(opt = "-i", type = "float", var_name = 'idx', opt_str = "-i=integer", desc = 'Index to speify alpha', # defval = 5, optional = False); # app.add_argument(opt = None, type = "str", var_name = 'infile', opt_str = "infile", desc = 'Input file', # defval = "input.txt", optional = False); # app.add_argument(opt = None, type = "str", var_name = 'nmax', opt_str = "nmax", desc = 'Max number of interation', # defval = 5, optional = False); args_opt, args_idx, args_vars = app.read_args(vars = cparams.__dict__, check_allowed_args = True) if args_opt is None: error_no = args_idx error_message = args_vars app.terminate("\n\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" + f"! {error_message}\n" + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", usage = app.usage) app.set_usage(usage_str) """ print("cparams.__dict__=", cparams.__dict__) app.usage() exit() """
[ドキュメント] def create_menu(app, config, cparams, root_window): """ 概要: アプリケーションのメニューバーを作成します。 詳細説明: 「ファイル」メニュー(開く、終了)と「ツール」メニュー(設定)を含むメニューバーを作成します。 メニュー項目にはアクセラレータキーも設定されます。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param root_window: tk.Tk: メインウィンドウのルートオブジェクト。 :returns: tk.Menu: 作成されたメニューバーオブジェクト。 """ def onOpen(event = None): # data_path_button_click(app, tkvars) print("") self.print_warning("Warning: This function is not impletmented") menu_bar = app.create_menu() menu_file = tktkinter.Menu(app, menu_bar, tearoff = 0) menu_file.add_command(label = app.p('Open'), accelerator = 'Alt+O', command = onOpen) # command = lambda: data_path_button_click(app, tkvars)) menu_file.add_command(label = app.p('exit'), accelerator='Alt+E', command = lambda e: app.on_closing()) menu_bar.add_cascade(label = app.p('File'), menu = menu_file) setup_widgets = 'editor_path|python3_path|pythonw_path|perl_path|' \ + 'start_path|shell_path|filer_path|vesta_path|confirm_on_exit|debug_mode' menu_tool = tk.Menu(menu_bar, tearoff = 0) menu_tool.add_command(label = app.p('Setup'), accelerator = 'Alt+u', command = lambda e: app.dialog_setup(widgets = setup_widgets)) menu_bar.add_cascade(label = app.p('Tool'), menu = menu_tool) menu_bar.bind_all("<Alt-o>", onOpen) menu_bar.bind_all("<Alt-e>", lambda e: app.on_closing()) menu_bar.bind_all("<Alt-u>", lambda e: app.dialog_setup(widgets = setup_widgets)) return menu_bar
[ドキュメント] def create_toolbar(app, config, cparams, root_window): """ 概要: アプリケーションのツールバーを作成します。 詳細説明: 設定ボタン、言語選択コンボボックス、終了ボタン、およびカスタムアクションを実行するための汎用ボタン(TButton)をツールバーに配置します。 各ボタンにはクリックイベントがバインドされます。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param root_window: tk.Tk: メインウィンドウのルートオブジェクト。 :returns: tk.Frame: 作成されたツールバーのフレームオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() config = app.configparams def toolbar_clickevent(event): pass tool_bar = app.create_toolbar(bg = 'blue') #============================================================== # Setup and edit inifile buttons #============================================================== setupButton = tktkinter.Button(app, tool_bar, text = "Setup", font = ("", config.font_size), command = lambda: app.setup()) setupButton.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0) """ def edit_inifile(): editor = config.get("editor_path", None) if editor is None== '' or editor == '': editors = app.get_editors() if len(editors) > 0: editor = editors[0] tktkinter.dialog_okcancel(app, title = app.p('Error'), message = 'editor_path is not specified.\nUse {editor}') else: tktkinter.dialog_okcancel(app, title = app.p('Error'), message = 'editor_path is not specified.') return # tktkinter.execute_command(app, config.editor_path, working_dir = '.', is_print = True, files = [config.inifile]) tkScript().execute_external_command(app, config.editor_path, [config.inifile], is_print = False) edit_ini_Button = tktkinter.Button(app, tool_bar, text = 'Edit ini file', font = ("", config.font_size), command = edit_inifile) edit_ini_Button.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0) """ #============================================================== # Extra buttons #============================================================== def tbutton_clicked2(e, app, menu, i_mouse_button): app.s_engine.execute(app, cparams, menu, idx = None, action = None, i_mouse_button = i_mouse_button, event = e) def tbutton_clicked(e, app, menu, i_mouse_button): app.root_window.after(1, lambda: tbutton_clicked2(e, app, menu, i_mouse_button)) def bind_tbutton(i): b = tkvars['tbuttons'][i] b.bind("<Button-1>", lambda e: tbutton_clicked(e, app, f'[TButton{i+1}]', '1')) b.bind("<Button-2>", lambda e: tbutton_clicked(e, app, f'[TButton{i+1}]', '2')) b.bind("<Button-3>", lambda e: tbutton_clicked(e, app, f'[TButton{i+1}]', '3')) b.bind("<Double-Button-1>", lambda e: tbutton_clicked(e, app, f'[TButton{i+1}]', 'd')) tkvars['tbuttons'] = [] for i in range(1, config.n_tbutton+1): tbutton = tktkinter.Button(app, tool_bar, text = '', font = ("", config.font_size)) tbutton.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0) tkvars['tbuttons'].append(tbutton) for i in range(config.n_tbutton): bind_tbutton(i) #============================================================== # Exit button #============================================================== def lang_sel_change(e): config.lang = tkvars['lang_combobox'].get() phrases = {'WillApplyUponReboot': {'ja': f'日本語に変更されました。再起動後に有効になります', 'en': f'Changed to English. Will be applied after reboot' } } app.phrases = app.read_resource(app.resource_path, config.lang, app.phrases) tktkinter.dialog_okcancel(app, title = app.p('Quit'), message = app.p('WillApplyUponReboot', phrases = phrases)) tkvars['lang'] = tk.StringVar(value = config.lang) # optionmenu = tk.OptionMenu(tool_bar, tool_bar, 'ja', 'en') # optionmenu.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0) combobox = tk.ttk.Combobox(tool_bar, values = ('ja', 'en'), width = 2) combobox.set(tkvars['lang'].get()) combobox.bind('<<ComboboxSelected>>', lang_sel_change) combobox.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0) tkvars['lang_combobox'] = combobox exitButton = tktkinter.Button(app, tool_bar, text = 'Exit', font = ("", config.font_size), command = lambda: app.on_closing(), anchor = tk.NW) exitButton.pack(side = tk.LEFT, anchor = 'w', padx = 1, pady = 0)
[ドキュメント] def input_path_button_click(app, cparams, tkvars, varname = "infile", parameterpath_varname = "prmpath", outputpath_varname = "outfile", file_type = [("Excel", "*.xlsx"), ("All", "*.*")], ini_dir = '.'): """ 概要: ファイル選択ダイアログを開き、選択されたファイルのパスを変数に設定します。 詳細説明: `tk.filedialog.askopenfilename` を使用してユーザーにファイルの選択を促し、選択されたファイルのパスを `tkvars[varname]` に設定します。 また、出力ファイルパス (`cparams.outfile`) とパラメータファイルパス (`cparams.parameter_path`) も推測して設定します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param tkvars: dict: GUIウィジェットの変数辞書。 :param varname: str: ファイルパスを格納する `tkvars` 内のキー名。デフォルトは "infile"。 :param parameterpath_varname: str: パラメータファイルパスを格納する `tkvars` 内のキー名。デフォルトは "prmpath"。 :param outputpath_varname: str: 出力ファイルパスを格納する `tkvars` 内のキー名。デフォルトは "outfile"。 :param file_type: list: ファイルダイアログで表示されるファイルタイプのリスト。デフォルトは Excelと全てのファイル。 :param ini_dir: str: ファイルダイアログの初期ディレクトリ。デフォルトは '.'。 """ selpath = tk.filedialog.askopenfilename(filetypes = file_type, initialdir = ini_dir) header, ext = os.path.splitext(selpath) filebody = os.path.basename(header) cparams.outfile = header + f'-predict.xlsx' cparams.parameter_path = header + '.prm' tkvars[varname].set(selpath) tkvars[outputpath_varname].set(cparams.outfile)
# tkvars[parameterpath_varname].set(cparams.parameter_path)
[ドキュメント] def copy_tkvars(app, cparams, tkvars): """ 概要: Tkinter変数の値をアプリケーションのパラメータオブジェクトにコピーします。 詳細説明: 現在の実装では、この関数は何も処理せずreturnします。 将来的にTkinterウィジェットの値を `cparams` や `config` に反映させるためのプレースホルダです。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param tkvars: dict: GUIウィジェットの変数辞書。 """ config = app.configparams return for key in ["fontsize", "legend_fontsize"]: cparams.set_attr(key, tkvars[key].get()) for key in ["fontsize", "legend_fontsize"]: config.set_attr(key, tkvars[key].get()) cparams.set_attr('figsize', [tkvars['fig_width'].get(), tkvars['fig_height'].get()])
[ドキュメント] def copy_config(app, cparams, config): """ 概要: `config` オブジェクトのパラメータを `cparams` オブジェクトにコピーします。 詳細説明: `config` オブジェクトと `cparams` オブジェクトで共通するキーについて、`cparams` の値を `config` の値で上書きします。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 """ keys0 = config.__dict__.keys() for key in cparams.__dict__.keys(): if key in keys0: cparams.set_attr(key, cparams.get(key, None))
[ドキュメント] def listbox_dbl_clicked(app, cparams, event): """ 概要: リストボックス項目がダブルクリックされた際のイベントハンドラです。 詳細説明: 現在の実装では、この関数は何も処理しません。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param event: tk.Event: イベントオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict()
# print("double clicked")
[ドキュメント] def set_tbutton_captions(app, cparams): """ 概要: ツールバーボタン(TButton)のキャプションを設定します。 詳細説明: `app.config.n_tbutton` で定義された数のTButtonについて、スクリプトエンジンから対応するキャプションを取得し、GUIに表示します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 """ tkvars = app.tkvars.get_param_dict() for i in range(app.config.n_tbutton): caption = app.s_engine.get_caption(app, f'[TButton{i+1}]') tkvars["tbuttons"][i].set_text(caption)
[ドキュメント] def set_rbutton_captions(app, cparams): """ 概要: 右サイドバーボタン(RButton)のキャプションを設定します。 詳細説明: `app.config.n_rbutton` で定義された数のRButtonについて、スクリプトエンジンから対応するキャプションを取得し、GUIに表示します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 """ tkvars = app.tkvars.get_param_dict() for i in range(app.config.n_rbutton): caption = app.s_engine.get_caption(app, f'[RButton{i+1}]') # print(f"{caption=}") tkvars["rbuttons"][i].set_text(caption)
# tkvars["rbuttons"][i]["text"] = app.p(caption)
[ドキュメント] def listbox_selected(app, cparams, event): """ 概要: メインメニューリストボックスの項目が選択された際のイベントハンドラです。 詳細説明: 選択されたメインメニューに対応するサブメニューボタンのキャプションと状態(有効/無効)を更新します。 また、ツールチップも設定します。スクリプトエンジンに 'select' アクションを通知します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param event: tk.Event: イベントオブジェクト。 """ # print("selected") # print("e=", type(event), event, event.widget) tkvars = app.tkvars.get_param_dict() sel = tkvars["menu_listbox"].curselection() # print("343 sel=", sel) if len(sel) == 0: return app.cur_sel = sel[0] # print("348 cur_sel=", app.cur_sel) menu = tkvars["menu_listbox"].get(sel) nbutton = len(tkvars["submenu_buttons"]) os_name = platform.system() if app.use_tooltip: for idx in range(nbutton): button = tkvars["submenu_buttons"][idx] tip = tkTooltip(widget = button, text = f'button {idx+1}', bg = '#dcfbfe', fg = '#0000ff') app.s_engine.execute(app, app.get_params(), menu, idx = None, action = 'select', i_mouse_button = 1, max_num = 1, event = event) submenus = app.s_engine.get_submenus(app, menu) for i in range(len(tkvars["submenu_buttons"])): tkvars["submenu_buttons"][i]["state"] = tk.DISABLED tkvars["submenu_buttons"][i]["text"] = '' tkvars["help_buttons"][i]["state"] = tk.DISABLED tkvars["help_buttons"][i].set_text('x') # tkvars["help_buttons"][i]["text"] = 'x' # print("submenus=", submenus) for m in submenus: idx = m['idx'] task = m['task'] caption = m['caption'] if task == '': # print(f"button {idx}={menu}") try: button = tkvars["submenu_buttons"][idx-1] except: print("") print(f"Error in Launcher.listbox_selected(): Menu idx {idx} for {menu} exceeds [{app.config.n_buttons}]") continue button.set_text(caption) # button.configure(text = app.p(caption)) # button["text"] = caption button["state"] = tk.NORMAL elif task == 'help': button = tkvars["help_buttons"][idx-1] button.set_text('?') # button["text"] = '?' button["state"] = tk.NORMAL
[ドキュメント] def initialize_launcher_menus(app, cparams): """ 概要: ランチャーのメニューとスクリプトエンジンを初期化します。 詳細説明: ランチャースクリプトディレクトリから `.ini` ファイルを読み込み、利用可能なスクリプトファイルを登録します。 `[Boot]` セクションなどの初期スクリプトを実行し、スクリプトエンジンを更新してメインメニューをリストボックスに表示します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 """ tkvars = app.tkvars.get_param_dict() print("") app.print_warning("Script files:") files = glob.glob(os.path.join(app.launcher_script_dir, '*.ini')) app.script_files = {} for f in app.extra_scripts + files: dirname, basename, filebody, ext = split_file_path(f) app.print_warning(f" [{basename}] in [{dirname}]") if basename in app.remove_scripts: app.print_warning(f" [{basename}] is in the remove script list. Skipped.") continue if not os.path.isfile(f): app.print_warning(f" [{basename}] does not exist. Skipped.") continue app.script_files[basename] = { "dir": dirname, "filebody": filebody, "filename": basename, "path": f } script_files = sorted(app.script_files.items()) app.s_engine = app.create_script() print("") app.print_warning(f"Read resource file [{app.resource_path}]:") app.phrases = app.read_resource(app.resource_path, app.config.lang) #, app.phrases) os_name = platform.system() menus = ['[Boot]', f'[Boot-{os_name}]'] if os_name == 'Linux': desktop = desktop_name() if desktop is not None: menus = ['[Boot]', f'[Boot-{os_name}]', f'[Boot-{desktop}'] for menu in menus: for fname in app.script_files.keys(): d = app.script_files[fname] path = d["path"] path, fp, line = app.s_engine.find_file_from_menu(app, menu, idx = None, task = None, script_files = [path]) if fp is None: continue else: app.s_engine.execute(app, app.get_params(), menu, idx = None, action = None, i_mouse_button = None, script_files = [path]) app.update_script_vars(app.get_params()) v = app.s_engine.update_script_vars(app, cparams) menus = app.s_engine.get_main_menus(app) print("") print("Initialize Launcher menu") # tkvars["menu_listbox"].delete(0, tk.END) tkvars["menu_listbox"].clear() for menu in menus: tkvars["menu_listbox"].insert(tk.END, app.p(menu)) tkvars["menu_listbox"].select_set(0) listbox_selected(app, cparams, None)
# button_type: menu, help # action: 1, 2, d1 for left button, right button, double click
[ドキュメント] def button_clicked2(app, cparams, ibutton, button_type, action, event = None): """ 概要: サブメニューボタンまたはヘルプボタンがクリックされた際の実際の処理を実行します。 詳細説明: 選択されているメインメニュー項目と、クリックされたサブボタンのインデックス、ボタンの種類(サブメニュー、ヘルプ)、 アクション(クリック、ダブルクリック)に基づいて、スクリプトエンジンにコマンドを実行させます。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param ibutton: int: クリックされたサブメニューボタンまたはヘルプボタンのインデックス(1始まり)。 :param button_type: str: クリックされたボタンの種類 ('submenu' または 'help')。 :param action: str: クリックアクションの種類 ('1' (左クリック), '2' (中クリック), '3' (右クリック), 'd1' (ダブルクリック))。 :param event: tk.Event, optional: イベントオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() sel = tkvars["menu_listbox"].curselection() # print(f"441 sel={sel}") if sel is None or len(sel) == 0: sel = app.cur_sel if sel is not None: tkvars["menu_listbox"].select_set(sel) if sel is None: tktkinter.dialog_showerror(app, title = 'Error', message = 'Select main menu') return # print(f"448 sel={sel}") menu = tkvars["menu_listbox"].get(sel) app.last_ibutton = ibutton app.update_script_vars(cparams) # print(f"cliecked: {ibutton} {button_type} {action}") button_type = button_type.lower() if button_type == 'submenu': if action == '1': app.s_engine.execute(app, cparams, menu, ibutton, '', 1, event = event) elif action == '2': app.s_engine.execute(app, cparams, menu, ibutton, '', 2, event = event) elif action == '3': app.s_engine.execute(app, cparams, menu, ibutton, '', 3, event = event) elif action == 'd1': app.s_engine.execute(app, cparams, menu, ibutton, 'dblclick', 1, event = event) elif button_type == 'help': if action == '1': app.s_engine.execute(app, cparams, menu, ibutton, 'help', 1, event = event) elif action == '2': app.s_engine.execute(app, cparams, menu, ibutton, 'help', 2, event = event) elif action == '3': app.s_engine.execute(app, cparams, menu, ibutton, 'help', 3, event = event) elif action == 'd1': app.s_engine.execute(app, cparams, menu, ibutton, 'dblclick', 1, event = event)
[ドキュメント] def button_clicked(app, cparams, ibutton, button_type, action, event = None): """ 概要: サブメニューボタンまたはヘルプボタンがクリックされた際のイベントハンドラです。 詳細説明: UIの応答性を保つため、`button_clicked2` の実際の処理を `app.root_window.after(1, ...)` を使って、 Tkinterのイベントループの次のサイクルで実行するようにスケジュールします。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param ibutton: int: クリックされたサブメニューボタンまたはヘルプボタンのインデックス(1始まり)。 :param button_type: str: クリックされたボタンの種類 ('submenu' または 'help')。 :param action: str: クリックアクションの種類 ('1' (左クリック), '2' (中クリック), '3' (右クリック), 'd1' (ダブルクリック))。 :param event: tk.Event, optional: イベントオブジェクト。 """ app.root_window.after(1, lambda: button_clicked2(app, cparams, ibutton, button_type, action, event = event))
[ドキュメント] def create_frame(app, config, cparams, parent_notebook): """ 概要: ランチャーのメインGUIフレームを作成し、様々なウィジェットを配置します。 詳細説明: メニューリストボックス、右サイドバーボタン、ファイルパス入力フィールド、コマンドライン入力フィールド、 サブメニューボタン、メッセージボックスなどを含むフレームを作成し、親のノートブックに追加します。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 :param parent_notebook: tk.ttk.Notebook: ウィジェットを追加する親のノートブックウィジェット。 :returns: tktkinter.Frame: 作成されたメインGUIフレーム。 """ config = app.configparams ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray') page1_frame.pack(fill = tk.BOTH, expand = True) parent_notebook.add(page1_frame, text = app.p('Menu')) notebook_frame = page1_frame applications = app.get_external_apps(config.get("editor_path", None)) # Listbox # https://www.shido.info/py/tkinter6.html top_frame = tk.Frame(page1_frame, bg = 'white') listbox_frame = tk.Frame(top_frame) listbox = tktkinter.tkScrolledListbox(listbox_frame, width = config.width_listbox, height = config.height_listbox, font = ("", config.font_size), borderwidth = 2, relief = "groove", cursor = 'arrow', fg = 'black', selectmode = 'browse', takefocus = True, state = 'normal', justify = 'left') listbox.frame.pack(side = tk.TOP, anchor = 'w', padx = 2, pady = 2) # listbox.frame.pack(side = tk.TOP, anchor = 'w', padx = 2, pady = 2, fill = tk.BOTH, expand = True) # listbox.bind("<<Button-1>>", listbox_selected) # listbox.bind("<<Button-2>>", listbox_selected) listbox.bind("<<ListboxSelect>>", lambda e: listbox_selected(app, cparams, e)) listbox.bind("<Double-Button-1>", lambda e: listbox_dbl_clicked(app, cparams, e)) tkvars["menu_listbox"] = listbox listbox_frame.pack(side = tk.LEFT, padx = 2, pady = 2, fill = tk.BOTH, expand = True) # Right buttons rbutton_frame = tk.Frame(top_frame) tkvars['rbuttons'] = [] for i in range(1, config.n_rbutton+1): rbutton = tktkinter.Button(app, rbutton_frame, text = '', width = config.width_rbutton, font = ("", config.font_size)) rbutton.pack(side = tk.TOP, fill = tk.BOTH, expand = True) tkvars['rbuttons'].append(rbutton) def rbutton_clicked2(e, app, menu, i_mouse_button): app.s_engine.execute(app, cparams, menu, idx = None, action = None, i_mouse_button = i_mouse_button, event = 3) def rbutton_clicked(e, app, menu, i_mouse_button): app.root_window.after(1, lambda: rbutton_clicked2(e, app, menu, i_mouse_button)) def bind_rbutton(i): b = tkvars['rbuttons'][i] b.bind("<Button-1>", lambda e: rbutton_clicked(e, app, f'[RButton{i+1}]', '1')) b.bind("<Button-2>", lambda e: rbutton_clicked(e, app, f'[RButton{i+1}]', '2')) b.bind("<Button-3>", lambda e: rbutton_clicked(e, app, f'[RButton{i+1}]', '3')) b.bind("<Double-Button-1>", lambda e: rbutton_clicked(e, app, f'[RButton{i+1}]', 'd')) for i in range(config.n_rbutton): bind_rbutton(i) rbutton_frame.pack(side = tk.LEFT, anchor = 'nw', padx = 2, pady = 2, fill = tk.BOTH, expand = True) top_frame.pack(side = tk.TOP, anchor = 'nw', padx = 2, pady = 2, fill = tk.BOTH, expand = True) # Input path frame def open_file(input_entry, output_entry = None, file_type = None, ini_dir = '.'): tktkinter.path_button_click(app, input_entry, file_type = file_type, ini_dir = ini_dir) if output_entry: header, ext = os.path.splitext(input_entry.get()) filebody = os.path.basename(header) outfile = header + f'-predict.xlsx' output_entry.set(outfile) path_grid_frame = tk.Frame(page1_frame) tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'sel_file', file_type = [("All", "*.*")], working_dir = '.', head_label_width = 6, entry_width = 35, button_width = 4, edit_button_width = 0, shell_button_width = 0, optionmenu_width = 4, open_command = lambda app, cparams, file_type, ini_dir: \ open_file(tkvars["sel_file"], None, file_type, ini_dir), # post_open_command = lambda: post_open(tkvars["infile"], tkvars["outfile"]), font_size = config.path_frame_font_size, is_print = True, igridrow = 0) path_grid_frame = tk.Frame(page1_frame) tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'argument', head_label_width = 5, entry_width = 40, button_width = 0, edit_button_width = 0, shell_button_width = 0, optionmenu_width = 0, font_size = config.path_frame_font_size, igridrow = 1) # Menu buttons def add_buttons(parent, idx): frame = tk.Frame(parent, bg = 'white') button = tktkinter.Button(app, frame, text = '', #f'Button {c}', width = config.width_submenu_button, font = ("", config.font_size), # command = lambda: analyze(app, cparams, tkvars) ) # button.grid(row = iy, column = ix) button.pack(side = tk.LEFT, anchor = 'w', padx = 0, pady = 0, fill = tk.X, expand = True) hbutton = tktkinter.Button(app, frame, text = '?', # width = config.width_help_button, height = config.height_help_button, font = ("", config.help_button_font_size), # command = lambda: analyze(app, cparams, tkvars), ) hbutton.pack(side = tk.LEFT, anchor = 'nw', padx = 0, pady = 0) frame.grid(row = iy, column = ix) button.bind("<Button-1>", lambda e: button_clicked(app, cparams, idx, 'submenu', '1', event = e)) button.bind("<Button-2>", lambda e: button_clicked(app, cparams, idx, 'submenu', '2', event = e)) button.bind("<Button-3>", lambda e: button_clicked(app, cparams, idx, 'submenu', '3', event = e)) button.bind("<Double-Button-1>", lambda e: button_clicked(app, cparams, idx, 'submenu', 'd1', event = e)) hbutton.bind("<Button-1>", lambda e: button_clicked(app, cparams, idx, 'help', '1', event = e)) hbutton.bind("<Button-2>", lambda e: button_clicked(app, cparams, idx, 'help', '2', event = e)) hbutton.bind("<Button-3>", lambda e: button_clicked(app, cparams, idx, 'help', '3', event = e)) hbutton.bind("<Double-Button-1>", lambda e: button_clicked(app, cparams, idx, 'help', 'd1', event = e)) tkvars["submenu_buttons"].append(button) tkvars["help_buttons"].append(hbutton) return button, hbutton button_grid_frame = tk.Frame(page1_frame, bg = 'white') tkvars["submenu_buttons"] = [] tkvars["help_buttons"] = [] c = 0 for iy in range(config.ny_button): for ix in range(config.nx_button): button, hbutton = add_buttons(button_grid_frame, c) c += 1 # button_grid_frame.grid_propagate(True) button_grid_frame.pack(side = tk.TOP, anchor = 'w', padx = 2, pady = 2, fill = tk.X, expand = True) # message box grid message_grid_frame = tk.Frame(page1_frame) tktkinter.make_path_frame(app, cparams, page1_frame, message_grid_frame, tkvars, varname = 'command_line_org', head_label_width = 10, entry_width = config.message_box_width, button_width = 0, edit_button_width = 0, shell_button_width = 0, optionmenu_width = 0, font_size = config.path_frame_font_size, igridrow = 0) def copy_to_clipboard(parent, entry_variable): print(f"copy [{entry_variable.get()}] to clipboard") parent.clipboard_clear() parent.clipboard_append(entry_variable.get()) parent.update_idletasks() tktkinter.make_path_frame(app, cparams, page1_frame, message_grid_frame, tkvars, varname = 'command_line', head_label_width = config.head_label_width, entry_width = config.message_box_width, button_width = 5, button_args = {'text': 'run', "width": 4, 'font': ("", config.font_size), 'command': lambda: app.s_engine.execute_a_command(app, cparams, tkvars['command_line'].get()) }, edit_button_width = 0, shell_button_width = 0, optionmenu_width = 0, copy_button_args = {'text': 'copy', "width": 4, 'font': ("", config.font_size), # 'command': lambda: copy_to_clipboard(page1_frame, tkvars['command_line'].get()), 'igridcol': 4 }, font_size = config.path_frame_font_size, igridrow = 1) tktkinter.make_path_frame(app, cparams, page1_frame, message_grid_frame, tkvars, varname = 'message', head_label_width = config.head_label_width, entry_width = config.message_box_width, button_width = 0, edit_button_width = 0, shell_button_width = 0, optionmenu_width = 0, font_size = config.path_frame_font_size, igridrow = 2) initialize_launcher_menus(app, cparams) set_tbutton_captions(app, cparams) set_rbutton_captions(app, cparams) os_name = platform.system() if app.use_tooltip: for idx in range(len(tkvars["tbuttons"])): button = tkvars["tbuttons"][idx] tkTooltip(widget = button, text = f'tbutton {idx+1}', bg = '#FFFF00', fg = '#0000FF') for idx in range(len(tkvars["rbuttons"])): button = tkvars["rbuttons"][idx] tkTooltip(widget = button, text = f'rbutton {idx+1}', bg = '#FFFF00', fg = '#0000FF') app.s_engine.execute(app, cparams, '[TButton].onload', idx = None, action = 'onload', i_mouse_button = None) app.s_engine.execute(app, cparams, '[RButton].onload', idx = None, action = 'onload', i_mouse_button = None) return notebook_frame
[ドキュメント] def create_window(app, config, cparams): """ 概要: アプリケーションのメインウィンドウとGUIコンポーネントを作成します。 詳細説明: メインウィンドウを作成し、メニューバー、ツールバー、およびメインフレームを配置します。 メインフレームには、ユーザーが操作する主要なウィジェットが含まれます。 :param app: tkLauncherApp: アプリケーションのインスタンス。 :param config: tkParams: 設定パラメータを格納するオブジェクト。 :param cparams: tkParams: 計算エンジンのパラメータオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() # iconfile = 'tkProg.ico' iconfile = os.path.join(os.environ.get('tkprog_X_path', '../'), 'tkProg.ico') os_name = platform.system() # print("os_name=", os_name) # print(f"Use icon file [{iconfile}]") if os_name == 'Linux' or not os.path.isfile(iconfile): root_window = app.create_window(title = app.window_title, geometry = config.geometry, minsize = config.minsize, default_font = ('FixedSys', config.default_font_size)) #None) #('FixedSys', 14)) else: root_window = app.create_window(title = app.window_title, iconfile = iconfile, geometry = config.geometry, minsize = config.minsize, default_font = ('FixedSys', config.default_font_size)) #None) #('FixedSys', 14)) app.main_window = root_window # menu_bar = create_menu(app, config, cparams, root_window) tool_bar = create_toolbar(app, config, cparams, root_window) # 2分割ウインドウを使う場合。いづれのpaneもnotebook型ウインドウが作られる # panes = app.add_root_panes(root = root_window, type = "pane2", sashwidth = 2, left_pane_width = 600) # main_pane, left_notebook, right_notebook = panes # 1p分割ウインドウを使う場合。paneはnotebook型ウインドウが作られる panes = app.add_root_panes(type = "pane1", sashwidth = 2) left_notebook = panes[0] # 左ペインのnotebookにタブを追加。2ページ目は開発者用タブ ltabframe1 = create_frame(app, config, cparams, left_notebook) ltabframe2 = app.create_development_tab(config, cparams, left_notebook, copy_tkvars = copy_tkvars) ltabframe3 = app.create_editor_tab(config, cparams, left_notebook, title = 'Editor test', entry_width = 35, eval_button_args = { 'text': 'eval', 'width': 4, "command": None }, )
[ドキュメント] def main(): """ 概要: アプリケーションのエントリポイントです。 詳細説明: アプリケーションの初期化、設定ファイルの読み込み、コマンドライン引数の解析、 GUIウィンドウの作成と表示、ログファイルの設定、および終了時の設定保存処理を行います。 `tkLauncherApp` インスタンスを作成し、設定パラメータとGUIウィジェット変数を管理します。 """ #================================================================== # Initialize parameters #================================================================== if platform.system() == 'Windows': user_ini_dir = get_user_inifile_dir(env_vars = [], dir_names = ['launcher']) else: user_ini_dir = get_user_inifile_dir(env_vars = ['HOME'], dir_names = ['.launcher', 'launcher']) app = tkLauncherApp(usage_str = usage_str, globals = globals(), locals = locals(), use_user_inifile = True, inifile_dirs = [user_ini_dir, '../../user', 'user'], create_inidir = False) print(f"Configuration file: {app.config.inifile}") # 設定パラメータオブジェクト config = app.config cparams = app.get_params() # 計算エンジンのパラメータオブジェクト # GUIウィジェット変数オブジェクトと辞書型 ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() mtime = time.localtime(os.path.getctime(app.script_path)) print("") print( "################################################") print(f"# {app.script_path} ver {version[0]}.{version[1]}.{version[2]}") print(f"# Modified time: {mtime.tm_year}/{mtime.tm_mon}/{mtime.tm_mday} {mtime.tm_hour}:{mtime.tm_min}:{mtime.tm_sec}") print( "################################################") print(f"Initialize parameters") initialize(app, config) print("") print(f"Read configration from [{config.inifile}]") config.read_parameters(path = config.inifile) if config.get('show_log', None): app.show_log = config.show_log print("") print(f"Add _path variables in {config.inifile} to environment vars") for key in config.__dict__.keys(): if '_path' in key: val = config.get(key, '') if val is not None: app.print(f" config[{key}]={val} is added") app.env[key] = val print("") print(f"Update parameters by command-line arguments") update_vars(app, cparams) config.n_buttons = config.nx_button * config.ny_button #=========================================== # logファイルへ保存 #=========================================== logfiles = [] if user_ini_dir: logfiles.append(os.path.join(user_ini_dir, "Launcher-out.txt")) logfiles.append(app.replace_path()) logfiles.append("Launcher-out.txt") config.logfile = None for path in logfiles: #ファイルが無いときもFalseが返るので、tryに置き換え # if os.access(path, os.W_OK): try: fout = open(path, "a") fout.close() config.logfile = path break except: path = os.path.join(user_ini_dir, "Launcher-out.txt") try: fout = open(path, "a") fout.close() config.logfile = path break except: print(f"\nWarning in main(): Can not write log to [{path}]") if config.logfile is None: print(f"\nWarning in main(): Can not create log file. Output log will not be save") # app.show_log = True print(f"Open logfile [{config.logfile}]") if app.show_log: app.redict(targets = ["stdout", config.logfile], mode = 'w') else: app.redict(targets = [config.logfile], mode = 'w') # python_pathとpython3_pathを強制的に一致させる config.python_path = config.python3_path # VSCodeのパスにスペースが入っていて問題が起こるので、実行ファイル名だけにする if re.search(r'code(\.exe)?$', config.editor_path): config.editor_path = 'code' #=========================================== # 内部パラメータ #=========================================== os_name = platform.system() print("") print(f"OS: {os_name}") print("") print("Directories:") print(" tkProg_Root :", app.tkProg_Root) print(" tklib_Root :", app.tklib_Root) print(" pythonlib_path :", app.pythonlib_path) print(" perllib_path :", app.perllib_path) print(" tkprog_X_path :", app.tkprog_X_path) print(" internal_editor_path:", app.internal_editor_path) print(" tkapp_path :", app.tkapp_path) print(" tkapp_open_path :", app.tkapp_open_path) print(" tkapp_etc_path :", app.tkapp_etc_path) print(" tkprog_path :", app.tkprog_path) print(" launcher_script_dir :", app.launcher_script_dir) print("") print("External applications:") print(" editor_path :", config.editor_path) print(" python_path :", config.python_path) print(" python3_path:", config.python3_path) print(" pythonw_path:", config.pythonw_path) print(" perl_path :", config.perl_path) print(" vesta_path :", config.vesta_path) # Group名を取得 dirname, basename, filebody, ext = split_file_path(app.script_fullpath) # dirname = ".. /Launcher" # dirname, basename, filebody, ext = split_file_path(dirname) # dirname = "tkprog_X_path" last_dirname = get_last_directory(dirname) m = re.search(r"_(.*?)$", last_dirname) if m: app.group = m.groups()[0] else: app.group = "" # group listファイルの有無を確認 if cparams.script_list_name == '': if app.group != '': filename = f'{app.group}.list' else: filename = 'default.list' path = os.path.join(app.launcher_script_dir, '../../config/Launcher', filename) if os.path.exists(path): cparams.script_list_name = os.path.join('../config/Launcher', filename) else: cparams.script_list_name = "default" print("") print(f"Group : {app.group}") print(f"Script list: {cparams.script_list_name}") editor = config.get("editor_path", None) if editor is None or editor == '': editors = app.get_editors() if len(editors) > 0: config.editor_path = editors[0] if config.editor_path is not None: app.env["tkEDITOR_PATH"] = config.editor_path def read_script_list(app, filebody): if '.list' in filebody: path = os.path.join(app.launcher_script_dir, '../', filebody) path = os.path.abspath(path) else: path = os.path.join(app.launcher_script_dir, f'{filebody}.list') cparams.script_list_path = path print("") app.print_warning(f"Read script lists from [{path}]") app.extra_scripts = [] app.remove_scripts = [] fp = open_chardet(path, 'r', def_encoding = 'shift_jis') # print("line", fp.readline()) try: fp = open_chardet(path, 'r', def_encoding = 'shift_jis') # fp = open(path, 'r') except: app.print_warning(f" Warning: Can not read [{path}]") return None, None section = '' while 1: line = fp.readline() if not line: break if '[extra_scripts]' in line: section = 'add' continue elif '[remove_scripts]' in line: section = 'remove' continue line = line.strip() if line == '': continue if line[0] in "#:;": continue if section == 'add': path = os.path.abspath(os.path.join(app.launcher_script_dir, line)) app.extra_scripts.append(path) elif section == 'remove': app.remove_scripts.append(line) return app.extra_scripts, app.remove_scripts if cparams.script_list_name: read_script_list(app, cparams.script_list_name) # print("add=", app.extra_scripts) # print("remove=", app.remove_scripts) # exit() app.resource_path = os.path.join(app.resource_dir, f'resource_{app.config.lang}.resource') app.phrases = app.read_resource(app.resource_path, app.config.lang) #, app.phrases) # app.write_resource("resource.txt", 'w') create_window(app, config, cparams) app.mainloop() # ウィジェットの設定tkvarsをcparams,confgにコピー copy_tkvars(app, cparams, tkvars) copy_tkvars(app, config, tkvars) # メインウインドウサイズをconfigにコピー config.geometry = app.root_window_geometry print("") print(f"Save configuration to [{config.inifile}]") # app.print_warning(f"main(): config:") # config.print_parameters(use_warning = True) ret = config.save_parameters(path = config.inifile, section = 'Configure', sort_by_keys = True, IsPrint = False) if not ret: app.print_warning(f"\nError: Can not write configuration to [{config.inifile}]\n") # 必要があれば、入力ファイルに対応するパラメータファイルを保存 if tkvars.get("prmpath", None) is not None: cparams.prmpath = tkvars["prmpath"].get() #os.path.splitext(cparams.path)[0] + '.prm' if cparams.prmpath != '': print(f"Save parameters to [{cparams.prmpath}]") ret = cparams.save_parameters(cparams.prmpath, section = 'Parameters', sort_by_keys = True, IsPrint = False, update_commandline = False) if not ret: app.terminate(f"Error in main(): Cannot write parameters to [{cparams.prmpath}]", usage = usage) app.terminate(usage = app.usage())
if __name__ == "__main__": main()