Coverage for graphica/gui/builders/property_widgets.py: 96.5%

105 statements  

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

1"""プロパティの見た目の部品: 線の種類のセグメント、太さ・透明度のスライダー、平滑化のスイッチ、色のチップ、 

2シンプルの種類のタイルと「アドバンスドですべて表示」の案内。 

3 

4値の持ち主は今のコンボ・スピンボックス・チェックボックスのまま(バインディングの表はそちらを見る)。 

5バインディングで戻すとシグナルが止まるので、戻したあとに refresh_property_widgets() で見た目を合わせる。 

6""" 

7from PySide6.QtCore import Qt 

8from PySide6.QtWidgets import QFrame, QHBoxLayout, QLabel, QPushButton, QVBoxLayout, QWidget 

9 

10from graphica.core.i18n import tr 

11from graphica.gui import theme 

12from graphica.gui.builders.common import _svg_icon 

13from graphica.gui.dataset_bindings import NO_MARKER 

14from graphica.gui.widgets import ComboMirror, SegmentedControl, SliderSpin, TypeTileGroup 

15 

16LINE_STYLE_ITEMS = (("solid", "実線"), ("dashed", "破線"), ("dotted", "点線"), ("dashdot", "一点鎖線")) 

17 

18# (絵, 表示名, 種別のコンボの値) 

19TYPE_TILES = ( 

20 ("line", "線", "Line"), 

21 ("scatter", "点", "Scatter"), 

22 ("line_scatter", "線+点", "Line+Scatter"), 

23 ("bar", "棒", "Bar"), 

24) 

25# 点を描く種類。マーカーが「なし」のまま選ぶと何も見えないので、円にする 

26_MARKER_TYPES = ("Scatter", "Line+Scatter") 

27_DEFAULT_MARKER = "o" 

28 

29# スライダーの範囲(よく使う範囲。数値の欄はこれより外の値も受け付ける) 

30LINEWIDTH_SLIDER_RANGE = (0.0, 5.0) 

31ALPHA_SLIDER_RANGE = (0.0, 1.0) 

32 

33QUICK_COLOR_COUNT = 4 

34 

35 

36class _TypeTileMirror(ComboMirror): 

37 """タイルで点を描く種類を選んだとき、マーカーが無ければ円にする。種類の変更と1つの「元に戻す」にまとめる。""" 

38 

39 def __init__(self, view, combo, app): 

40 self._app = app 

41 super().__init__(view, combo) 

42 

43 def _on_view_changed(self, index): 

44 app = self._app 

45 needs_marker = (self.view.itemData(index) in _MARKER_TYPES 

46 and app.ui.marker_combo.currentData() == NO_MARKER) 

47 if not needs_marker: 

48 super()._on_view_changed(index) 

49 return 

50 app.undo_stack.beginMacro(tr("グラフの種類")) 

51 try: 

52 app.ui.marker_combo.setCurrentIndex(app.ui.marker_combo.findData(_DEFAULT_MARKER)) 

53 super()._on_view_changed(index) 

54 finally: 

55 app.undo_stack.endMacro() 

56 

57 

58def _swap_field(form, old_field, new_field): 

59 """フォームの欄を差し替える(行の位置はそのまま)。old_field は new_field の中に取り込む前に呼ぶこと。""" 

60 if form.replaceWidget(old_field, new_field) is None: 60 ↛ 61line 60 didn't jump to line 61 because the condition on line 60 was never true

61 raise ValueError("欄がフォームに見つからない") 

62 

63 

64def _hidden_owner_row(view, owner): 

65 """見た目の部品と、隠した値の持ち主(コンボ)を1つの欄にまとめる(持ち主が節の外に浮かないように)。""" 

66 field = QWidget() 

67 layout = QHBoxLayout(field) 

68 layout.setContentsMargins(0, 0, 0, 0) 

69 layout.setSpacing(0) 

70 layout.addWidget(view, 1) 

71 owner.setParent(field) 

72 owner.hide() 

73 return field 

74 

75 

76def build_property_widgets(app): 

77 """基本スタイルの節の部品を見本の形に替える。build_dataset_style_controls の最後に呼ぶ(行が全部できた後)。""" 

78 style_form = app._prop_form('style') 

79 

80 # 線の種類: 線の絵のセグメント 

81 app.linestyle_segments = SegmentedControl() 

82 for line_style, tooltip in LINE_STYLE_ITEMS: 

83 app.linestyle_segments.addLineStyleItem(line_style, tooltip=tr(tooltip)) 

84 placeholder = QWidget() 

85 _swap_field(style_form, app.ui.linestyle_combo, placeholder) 

86 app.linestyle_field = _hidden_owner_row(app.linestyle_segments, app.ui.linestyle_combo) 

87 _swap_field(style_form, placeholder, app.linestyle_field) 

88 placeholder.deleteLater() 

89 app.linestyle_mirror = ComboMirror(app.linestyle_segments, app.ui.linestyle_combo) 

90 

91 # 線の太さ・透明度: スライダー+数値(数値の欄は今のスピンボックス) 

92 app.linewidth_slider = _slider_field(style_form, app.ui.linewidth_spinbox, *LINEWIDTH_SLIDER_RANGE) 

93 app.alpha_slider = _slider_field(style_form, app.alpha_spinbox, *ALPHA_SLIDER_RANGE) 

94 

95 # 平滑化: 部品は替えず、描き方だけスイッチに 

96 theme.make_toggle_switch(app.ui.smoothing_checkbox) 

97 

98 # 色: 見本の右に、今の配色パレットの色 

99 app.color_picker_widget.show_quick_colors(quick_colors(app)) 

100 

101 # シンプルの種類: アイコンの4択(裏で「種別」のコンボを書く) 

102 app.plot_type_tiles = TypeTileGroup() 

103 for glyph, text, value in TYPE_TILES: 

104 app.plot_type_tiles.addTile(glyph, tr(text), value) 

105 app.plot_type_tiles_mirror = _TypeTileMirror(app.plot_type_tiles, app.ui.plot_type_combo, app) 

106 app._plot_type_tiles_row.layout().addWidget(app.plot_type_tiles) 

107 

108 app.lite_more_box = _build_lite_more_box(app) 

109 app._dataset_property_sections_container.layout().addWidget(app.lite_more_box) 

110 

111 

112def _slider_field(form, spinbox, slider_min, slider_max): 

113 placeholder = QWidget() 

114 _swap_field(form, spinbox, placeholder) 

115 slider = SliderSpin(spinbox, slider_min, slider_max) 

116 _swap_field(form, placeholder, slider) 

117 placeholder.deleteLater() 

118 return slider 

119 

120 

121def _build_lite_more_box(app): 

122 """シンプルで隠している項目の案内と、アドバンスドに切り替えるリンク。""" 

123 box = QFrame() 

124 box.setObjectName("lite_more_box") 

125 layout = QVBoxLayout(box) 

126 layout.setContentsMargins(12, 10, 12, 10) 

127 layout.setSpacing(6) 

128 

129 row = QHBoxLayout() 

130 row.setSpacing(8) 

131 app.lite_more_icon = QLabel() 

132 app.lite_more_icon.setObjectName("lite_more_icon") 

133 app.lite_more_icon.setPixmap(_svg_icon("lock", size=15).pixmap(15, 15)) 

134 app.lite_more_icon.setAlignment(Qt.AlignmentFlag.AlignTop) 

135 text = QLabel(tr("誤差・透明度・平滑化・マーカー・グラデーション・ウォーターフォール・2D マップなど")) 

136 text.setObjectName("lite_more_text") 

137 text.setWordWrap(True) 

138 row.addWidget(app.lite_more_icon) 

139 row.addWidget(text, 1) 

140 layout.addLayout(row) 

141 

142 app.lite_more_button = QPushButton(tr("アドバンスドですべて表示 →")) 

143 app.lite_more_button.setObjectName("lite_more_button") 

144 app.lite_more_button.setFlat(True) 

145 app.lite_more_button.setCursor(Qt.CursorShape.PointingHandCursor) 

146 app.lite_more_button.clicked.connect(app.show_advanced_mode) 

147 layout.addWidget(app.lite_more_button, 0, Qt.AlignmentFlag.AlignLeft) 

148 return box 

149 

150 

151def quick_colors(app): 

152 return list(app.colors.active_color_cycle())[:QUICK_COLOR_COUNT] 

153 

154 

155def refresh_property_widgets(app): 

156 """バインディングで欄を戻したあと(シグナルが止まっている)、見た目の部品を合わせる。""" 

157 if not hasattr(app, 'linestyle_mirror'): 157 ↛ 158line 157 didn't jump to line 158 because the condition on line 157 was never true

158 return 

159 app.linestyle_mirror.refresh() 

160 app.plot_type_tiles_mirror.refresh() 

161 app.linewidth_slider.refresh() 

162 app.alpha_slider.refresh() 

163 app.color_picker_widget.show_quick_colors(quick_colors(app))