Coverage for graphica/gui/datasets/plugin_runs.py: 100.0%

66 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-12 16:38 +0000

1"""プラグインが登録したデータ処理と解析の実行。結果の追加は Undo できる。""" 

2import logging 

3from PySide6.QtWidgets import QDialog 

4 

5from graphica.gui import notify 

6from graphica.core.dataset import Dataset 

7from graphica.core.plugin_types import AnalysisResult, PluginExecutionError 

8from graphica.gui.dialogs import PluginParamDialog, ResultDialog 

9 

10logger = logging.getLogger(__name__) 

11 

12 

13class PluginRunController: 

14 """プラグインのデータ処理(processor)と解析(analyzer)を今のデータセットに対して実行する。""" 

15 

16 def __init__(self, host): 

17 self._host = host 

18 self.analysis_result_dialog = None 

19 

20 def run_processor(self, processor): 

21 """processor が返したデータセットを Undo できる形で足す(プラグイン側は Undo を意識しない)。""" 

22 dataset = self._host.current_dataset() 

23 if dataset is None: 

24 notify.information(self._host.parent_widget, processor.name, "データセットを選択してください。") 

25 return 

26 

27 params = {} 

28 if processor.param_schema: 

29 dialog = PluginParamDialog(processor.name, processor.param_schema, self._host.parent_widget) 

30 if dialog.exec() != QDialog.DialogCode.Accepted: 

31 return 

32 params = dialog.get_values() 

33 

34 try: 

35 new_dataset = processor.fn(dataset, params) 

36 if not isinstance(new_dataset, Dataset): 

37 raise TypeError(f"Datasetを返しませんでした(型: {type(new_dataset).__name__})。") 

38 except Exception as e: 

39 logger.exception("[plugin:%s] processor の実行に失敗しました", processor.plugin_name) 

40 notify.critical( 

41 self._host.parent_widget, "データ処理エラー", 

42 str(PluginExecutionError(processor.plugin_name, f"「{processor.name}」の実行に失敗しました: {e}")) 

43 ) 

44 return 

45 

46 # どのプラグインが作ったかを残す 

47 new_dataset.source_plugin = processor.plugin_name 

48 self._host.add_dataset_with_undo( 

49 new_dataset, self._host.target_folder_for_new_dataset(), 

50 description=f"データ処理: {processor.name}" 

51 ) 

52 self._host.show_status(f"「{new_dataset.name}」を追加しました") 

53 

54 def run_analyzer(self, analyzer): 

55 """analyzer の結果(派生データセット・注釈・表)を、それぞれ Undo できる形や結果の窓で反映する。""" 

56 dataset = self._host.current_dataset() 

57 if dataset is None: 

58 notify.information(self._host.parent_widget, analyzer.name, "データセットを選択してください。") 

59 return 

60 

61 params = {} 

62 if analyzer.param_schema: 

63 dialog = PluginParamDialog(analyzer.name, analyzer.param_schema, self._host.parent_widget) 

64 if dialog.exec() != QDialog.DialogCode.Accepted: 

65 return 

66 params = dialog.get_values() 

67 

68 try: 

69 result = analyzer.fn(dataset, params) 

70 if not isinstance(result, AnalysisResult): 

71 raise TypeError(f"AnalysisResultを返しませんでした(型: {type(result).__name__})。") 

72 except Exception as e: 

73 logger.exception("[plugin:%s] analyzer の実行に失敗しました", analyzer.plugin_name) 

74 notify.critical( 

75 self._host.parent_widget, "解析エラー", 

76 str(PluginExecutionError(analyzer.plugin_name, f"「{analyzer.name}」の実行に失敗しました: {e}")) 

77 ) 

78 return 

79 

80 if result.new_datasets: 

81 target_folder = self._host.target_folder_for_new_dataset() 

82 with self._host.deferred_redraw(): 

83 for new_dataset in result.new_datasets: 

84 new_dataset.source_plugin = analyzer.plugin_name 

85 self._host.add_dataset_with_undo( 

86 new_dataset, target_folder, description=f"解析による追加: {analyzer.name}" 

87 ) 

88 

89 if result.annotations: 

90 self._host.add_annotations_to_active_axis(result.annotations, f"解析による注釈追加: {analyzer.name}") 

91 

92 if result.table is not None: 

93 if self.analysis_result_dialog is not None: 

94 self.analysis_result_dialog.close() 

95 self.analysis_result_dialog = ResultDialog( 

96 analyzer.name, f"[{analyzer.name}] の解析結果", self._host.parent_widget, csv_data=result.table 

97 ) 

98 self.analysis_result_dialog.show() 

99 

100 self._host.show_status(f"「{analyzer.name}」を実行しました")