Coverage for graphica/gui/datasets/actions_menu.py: 100.0%
69 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
1"""データセット操作メニュー(ツリーの右クリックとツールバーのボタンで同じものを出す)。"""
2from PySide6.QtCore import Qt
3from PySide6.QtWidgets import QMenu
5from graphica.core.i18n import tr
8def populate_dataset_actions_menu(app, menu):
9 """
10 app(1つのタブ)の今の選択に合わせて menu の中身を作り直す。
12 選択に応じて出し入れする項目があるので、開くたびに作り直す。PySide6 が途中で
13 サブメニューを回収しないよう、Python 側の参照はメニュー自身に持たせる(_graphica_submenus)。
14 """
15 menu.clear()
16 submenus = []
18 def add_submenu(title):
19 """空のまま出さないよう、項目が入ったものだけ最後に menu へ繋ぐ。"""
20 sub = QMenu(title, menu)
21 submenus.append(sub)
22 return sub
24 data_proc_menu = add_submenu(tr("データ処理"))
25 analysis_menu = add_submenu(tr("解析・注釈"))
26 multi_menu = add_submenu(tr("複数データセット"))
27 export_menu = add_submenu(tr("エクスポート"))
28 tab_menu = add_submenu(tr("タブ操作"))
30 menu.addAction(tr("新しいフォルダ")).triggered.connect(app._on_new_folder)
31 if app.project.datasets:
32 menu.addAction(tr("すべて表示")).triggered.connect(app._on_show_all_datasets)
33 menu.addAction(tr("すべて非表示")).triggered.connect(app._on_hide_all_datasets)
35 current_item = app.ui.dataset_list_widget.currentItem()
36 if current_item is not None and current_item.data(0, Qt.ItemDataRole.UserRole) is None:
37 menu.addAction(tr("フォルダ名を変更...")).triggered.connect(app._on_rename_dataset_folder)
38 menu.addAction(tr("フォルダ内を全て表示")).triggered.connect(app._on_show_all_in_folder)
39 menu.addAction(tr("フォルダ内を全て非表示")).triggered.connect(app._on_hide_all_in_folder)
41 current = app._get_current_dataset()
42 if current is not None:
43 menu.addSeparator()
44 menu.addAction(tr("スタイルをコピー")).triggered.connect(app.transfer.copy_style)
45 paste_style_action = menu.addAction(tr("スタイルを貼り付け"))
46 paste_style_action.setEnabled(app.transfer.copied_style is not None)
47 paste_style_action.triggered.connect(app.transfer.paste_style)
48 # 元ファイルを持たないデータセット(貼り付け・演算・プラグインの生成物など)では使えない
49 reload_action = menu.addAction(tr("元ファイルから再読み込み"))
50 reload_action.setEnabled(bool(current.source_file))
51 reload_action.triggered.connect(app.transfer.reload_from_source)
53 processing = app.processing
54 for title, handler in (
55 ("規格化(ノーマライズ)...", processing.normalize),
56 ("Savitzky-Golayフィルタ(平滑化/微分)...", processing.savgol_smooth),
57 ("ベースライン補正...", processing.baseline_correction),
58 ("区間積分(台形則/Simpson則)...", processing.interval_integral),
59 ("累積積分(台形則/Simpson則)...", processing.cumulative_integral),
60 ("共通X格子へのリサンプリング/補間...", processing.resample),
61 ("重複X値の検出...", processing.detect_duplicate_x),
62 ("行フィルタ...", processing.filter_rows),
63 ("列の値で系列に分割...", processing.split_by_column),
64 ("外れ値検出(Z-score/IQR)...", processing.detect_outliers),
65 ):
66 data_proc_menu.addAction(tr(title)).triggered.connect(handler)
68 for title, handler in (
69 ("統計値アンカーラベルを追加...", app.overlays.add_stat_label),
70 ("インセット(拡大図)を追加...", app.overlays.add_inset),
71 ("ピーク位置に自動ラベルを追加...", app.peaks.add_peak_labels),
72 ("ヒストグラム / KDE...", processing.histogram_or_kde),
73 ):
74 analysis_menu.addAction(tr(title)).triggered.connect(handler)
76 # 対象外でも隠さずグレーアウトする(ある機能に気づけるように)
77 export_fit_action = export_menu.addAction(tr("フィット結果のエクスポート..."))
78 export_fit_action.setEnabled(current.fit_result is not None)
79 export_fit_action.triggered.connect(app.fitting.show_fit_result)
80 copy_methods_text_action = export_menu.addAction(tr("「方法」文をコピー..."))
81 copy_methods_text_action.setEnabled(current.provenance is not None)
82 copy_methods_text_action.triggered.connect(app.transfer.copy_methods_text)
84 selected = app._get_selected_datasets()
85 if len(selected) >= 2:
86 if len(selected) == 2:
87 multi_menu.addAction(tr("データセット間演算...")).triggered.connect(app.processing.arithmetic)
88 multi_menu.addAction(tr("X軸アライメント(相互相関)...")).triggered.connect(app.processing.align_selected)
89 multi_menu.addAction(tr("平均±SD生成...")).triggered.connect(app.processing.mean_and_sd_of_selected)
90 multi_menu.addAction(tr("バッチ列計算...")).triggered.connect(app.processing.batch_column_calculate)
91 multi_menu.addAction(tr("バッチカーブフィット...")).triggered.connect(app.fitting.batch_fit_selected)
93 if selected:
94 export_menu.addAction(tr("データ表をファイルに書き出す...")).triggered.connect(app.transfer.export_data)
95 # 他のタブが無くても出しておき、選んだときに案内する
96 tab_menu.addAction(tr("別のタブへコピー...")).triggered.connect(
97 lambda: app.transfer.copy_or_move_to_tab(move=False))
98 tab_menu.addAction(tr("別のタブへ移動...")).triggered.connect(
99 lambda: app.transfer.copy_or_move_to_tab(move=True))
101 attached_any = False
102 for sub in submenus:
103 if sub.actions():
104 if not attached_any:
105 menu.addSeparator()
106 attached_any = True
107 menu.addMenu(sub)
109 if app.ui.dataset_list_widget.selectedItems():
110 menu.addSeparator()
111 menu.addAction(tr("削除")).triggered.connect(app._on_remove_dataset)
113 menu._graphica_submenus = submenus
114 return menu