Coverage for graphica/core/plugin_context.py: 100.0%

24 statements  

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

1""" 

2プラグインが本体を操作するための窓口(プラグイン API 2.1)。 

3 

4メニューの callback とパネルの widget_factory が受け取る。1つのタブと1つのプラグインの 

5組ごとに1つ作られるので、どのメソッドも「そのタブ」を相手にする(複数タブでも取り違えない)。 

6本体の内部(PlotterApp やその private メソッド)には、この窓口の外から触らないこと。 

7本体の実装は gui/plugin_context.py、テスト用は core.plugin_testing.FakePluginContext。 

8""" 

9from contextlib import AbstractContextManager 

10from typing import TYPE_CHECKING, Any, Callable 

11if TYPE_CHECKING: 

12 from graphica.core.dataset import Dataset 

13 

14 

15class PluginContext: 

16 """プラグイン向けの窓口の仕様。メソッドの中身は実装側が持つ。""" 

17 

18 # --- データセット --- 

19 

20 def datasets(self) -> "list[Dataset]": 

21 """ 

22 タブの全データセットを返す。 

23 

24 Returns: 

25 list[Dataset]: 表示順。リスト自体はコピーなので、並べ替えても本体は変わらない。 

26 要素の Dataset は本体と同じオブジェクト。変更は set_dataset_properties() で行う。 

27 """ 

28 raise NotImplementedError 

29 

30 def current_dataset(self) -> "Dataset | None": 

31 """ 

32 Returns: 

33 Dataset | None: データセット一覧で現在選ばれているもの。なければ None。 

34 """ 

35 raise NotImplementedError 

36 

37 def selected_datasets(self) -> "list[Dataset]": 

38 """ 

39 Returns: 

40 list[Dataset]: データセット一覧で選択されているもの(複数選択を含む)。 

41 """ 

42 raise NotImplementedError 

43 

44 def add_dataset(self, dataset: "Dataset", description: str | None = None) -> None: 

45 """ 

46 データセットを追加する。Undo で取り消せる。 

47 

48 Args: 

49 dataset (Dataset): 追加するデータセット。 

50 description (str | None): 「元に戻す」メニューに出す説明。省略時は既定の文言。 

51 """ 

52 raise NotImplementedError 

53 

54 def set_dataset_properties(self, dataset: "Dataset", values: dict[str, Any], description: str | None = None) -> None: 

55 """ 

56 データセットの属性をまとめて変更し、再描画する。Undo で取り消せる。 

57 

58 Args: 

59 dataset (Dataset): 対象。datasets() などで得たもの。 

60 values (dict): {属性名: 新しい値}。例: {"color": "#1f77b4", "linewidth": 2.0} 

61 description (str | None): 「元に戻す」メニューに出す説明。 

62 Raises: 

63 AttributeError: Dataset に無い属性名が含まれる。 

64 """ 

65 raise NotImplementedError 

66 

67 def undo_group(self, description: str) -> AbstractContextManager[None]: 

68 """ 

69 with の中で行った add_dataset() と set_dataset_properties() を、Undo 1回分にまとめる(API 2.1)。 

70 

71 with ctx.undo_group("配色を適用"): 

72 for ds, color in zip(ctx.selected_datasets(), colors): 

73 ctx.set_dataset_properties(ds, {"color": color}) 

74 

75 何も変えなかったときは何も積まない。入れ子にすると外側の1回分にまとまる。 

76 with の中で例外が起きても、それまでの変更は1回分として残る(Undo で戻せる)。 

77 

78 Args: 

79 description (str): 「元に戻す」メニューに出す説明。 

80 """ 

81 raise NotImplementedError 

82 

83 def redraw(self) -> None: 

84 """グラフを描き直す。データセットの中身を直接変えたあとに呼ぶ。""" 

85 raise NotImplementedError 

86 

87 # --- 変化の通知 --- 

88 

89 def on_datasets_changed(self, callback: Callable[[], Any]) -> None: 

90 """ 

91 データセットの追加・削除・変更・プロジェクトの読み込みのあとに callback() を呼ぶ。 

92 パネルの表示を最新に保つのに使う。描き直しのたびに呼ばれるので、callback は軽くする。 

93 

94 Args: 

95 callback (callable): 引数なし。 

96 """ 

97 raise NotImplementedError 

98 

99 def on_selection_changed(self, callback: Callable[["Dataset | None"], Any]) -> None: 

100 """ 

101 データセット一覧の選択が変わったら callback(current_dataset) を呼ぶ。 

102 

103 Args: 

104 callback (callable): Dataset | None を1つ受け取る。 

105 """ 

106 raise NotImplementedError 

107 

108 # --- 画面 --- 

109 

110 @property 

111 def parent_widget(self) -> Any: 

112 """ 

113 Returns: 

114 QWidget | None: ダイアログの親にするウィンドウ。 

115 """ 

116 raise NotImplementedError 

117 

118 def show_message(self, text: str, title: str | None = None) -> None: 

119 """情報メッセージを表示する。title の省略時はプラグイン名。""" 

120 raise NotImplementedError 

121 

122 def show_error(self, text: str, title: str | None = None) -> None: 

123 """エラーメッセージを表示する。title の省略時はプラグイン名。""" 

124 raise NotImplementedError 

125 

126 # --- 保存場所 --- 

127 

128 @property 

129 def data_dir(self) -> str: 

130 """ 

131 Returns: 

132 str: このプラグイン専用の書き込み可能なフォルダ(無ければ作る)。設定やライブラリの保存先。 

133 本体のインストール先は読み取り専用のことがあるので、ここ以外には書かない。 

134 """ 

135 raise NotImplementedError 

136 

137 # --- 色 --- 

138 

139 def named_colors(self) -> list[dict[str, str]]: 

140 """ 

141 本体に登録された名前付きの色。 

142 

143 Returns: 

144 list[dict]: [{"name": str, "color": "#rrggbb"}, ...]。並び順は利用者が決めた表示順。 

145 """ 

146 raise NotImplementedError 

147 

148 def set_named_colors(self, entries: list[dict[str, str]]) -> None: 

149 """ 

150 名前付きの色を丸ごと置き換える。 

151 

152 Args: 

153 entries (list[dict]): named_colors() と同じ形。 

154 Raises: 

155 core.named_colors.NamedColorError: 名前か色コードが不正、または名前が重複している。 

156 """ 

157 raise NotImplementedError 

158 

159 def color_palettes(self) -> dict[str, list[str]]: 

160 """ 

161 利用者が作った配色パレット(組み込みのパレットは含まない)。 

162 

163 Returns: 

164 dict[str, list[str]]: {パレット名: ["#rrggbb", ...]} 

165 """ 

166 raise NotImplementedError 

167 

168 def set_color_palettes(self, palettes: dict[str, list[str]]) -> None: 

169 """ 

170 利用者の配色パレットを丸ごと置き換える。 

171 

172 Args: 

173 palettes (dict[str, list[str]]): color_palettes() と同じ形。 

174 Raises: 

175 ValueError: 形が不正、または色コードが不正。 

176 """ 

177 raise NotImplementedError 

178 

179 def active_color_cycle(self) -> list[str]: 

180 """ 

181 Returns: 

182 list[str]: いま選ばれているパレットの色(系列に順に割り当てる色)。 

183 """ 

184 raise NotImplementedError 

185 

186 def set_active_color_palette(self, name: str) -> None: 

187 """ 

188 配色パレットを「いま使うパレット」にする。パレット管理で選ぶのと同じ(API 2.1)。 

189 すでに描いている色は変えない。以後の自動配色が使う。 

190 

191 Args: 

192 name (str): 組み込みのパレット、利用者のパレット(color_palettes() のキー)、 

193 または matplotlib の既定の色を表す "Matplotlib既定" のいずれかの名前。 

194 Raises: 

195 ValueError: その名前のパレットが無い。 

196 """ 

197 raise NotImplementedError