1# (C) Copyright 2005-2020 Enthought, Inc., Austin, TX 2# All rights reserved. 3# 4# This software is provided without warranty under the terms of the BSD 5# license included in LICENSE.txt and may be redistributed only under 6# the conditions described in the aforementioned license. The license 7# is also available online at http://www.enthought.com/licenses/BSD.txt 8# 9# Thanks for using Enthought open source! 10 11""" Provides an AbstractValueType ABC for Pyface data models. 12 13This module provides an ABC for data view value types, which are responsible 14for adapting raw data values as used by the data model's ``get_value`` and 15``set_value`` methods to the data channels that the data view expects, such 16as text, color, icons, etc. 17 18It is up to the data view to take this standardized data and determine what 19and how to actually display it. 20""" 21 22from enum import IntEnum 23 24from traits.api import ABCHasStrictTraits, Event, observe 25 26from pyface.color import Color 27from .data_view_errors import DataViewSetError 28 29 30class CheckState(IntEnum): 31 "Possible checkbox states" 32 # XXX in the future this may need a "partial" state, see Pyface #695 33 UNCHECKED = 0 34 CHECKED = 1 35 36 37class AbstractValueType(ABCHasStrictTraits): 38 """ A value type converts raw data into data channels. 39 40 The data channels are editor value, text, color, image, and description. 41 The data channels are used by other parts of the code to produce the actual 42 display. 43 44 Subclasses should mark traits that potentially affect the display of values 45 with ``update_value_type=True`` metdadata, or alternatively fire the 46 ``updated`` event when the state of the value type changes. 47 48 Each data channel is set up to have a method which returns whether there 49 is a value for the channel, a second method which returns the value, 50 and an optional third method which sets the channel value. These methods 51 should not raise an Exception, eveen when called inappropriately (eg. 52 calling a "get" method after a "has" method has returned False). 53 """ 54 55 #: Fired when a change occurs that requires updating values. 56 updated = Event 57 58 def has_editor_value(self, model, row, column): 59 """ Return whether or not the value can be edited. 60 61 The default implementation is that cells that can be set are 62 editable. 63 64 Parameters 65 ---------- 66 model : AbstractDataModel 67 The data model holding the data. 68 row : sequence of int 69 The row in the data model being queried. 70 column : sequence of int 71 The column in the data model being queried. 72 73 Returns 74 ------- 75 has_editor_value : bool 76 Whether or not the value is editable. 77 """ 78 return model.can_set_value(row, column) 79 80 def get_editor_value(self, model, row, column): 81 """ Return a value suitable for editing. 82 83 The default implementation is to return the underlying data value 84 directly from the data model. 85 86 Parameters 87 ---------- 88 model : AbstractDataModel 89 The data model holding the data. 90 row : sequence of int 91 The row in the data model being queried. 92 column : sequence of int 93 The column in the data model being queried. 94 95 Returns 96 ------- 97 value : any 98 The value to edit. 99 """ 100 return model.get_value(row, column) 101 102 def set_editor_value(self, model, row, column, value): 103 """ Set a value that is returned from editing. 104 105 The default implementation is to set the value directly from the 106 data model. Returns True if successful, False if it fails. 107 108 Parameters 109 ---------- 110 model : AbstractDataModel 111 The data model holding the data. 112 row : sequence of int 113 The row in the data model being queried. 114 column : sequence of int 115 The column in the data model being queried. 116 value : any 117 The value to set. 118 119 Raises 120 ------- 121 DataViewSetError 122 If the value cannot be set. 123 """ 124 model.set_value(row, column, value) 125 126 def has_text(self, model, row, column): 127 """ Whether or not the value has a textual representation. 128 129 The default implementation returns True if ``get_text`` 130 returns a non-empty value. 131 132 Parameters 133 ---------- 134 model : AbstractDataModel 135 The data model holding the data. 136 row : sequence of int 137 The row in the data model being queried. 138 column : sequence of int 139 The column in the data model being queried. 140 141 Returns 142 ------- 143 has_text : bool 144 Whether or not the value has a textual representation. 145 """ 146 return self.get_text(model, row, column) != "" 147 148 def get_text(self, model, row, column): 149 """ The textual representation of the underlying value. 150 151 The default implementation calls str() on the underlying value. 152 153 Parameters 154 ---------- 155 model : AbstractDataModel 156 The data model holding the data. 157 row : sequence of int 158 The row in the data model being queried. 159 column : sequence of int 160 The column in the data model being queried. 161 162 Returns 163 ------- 164 text : str 165 The textual representation of the underlying value. 166 """ 167 return str(model.get_value(row, column)) 168 169 def set_text(self, model, row, column, text): 170 """ Set the text of the underlying value. 171 172 This is provided primarily for backends which may not permit 173 non-text editing of values, in which case this provides an 174 alternative route to setting the value. The default implementation 175 does not allow setting the text. 176 177 Parameters 178 ---------- 179 model : AbstractDataModel 180 The data model holding the data. 181 row : sequence of int 182 The row in the data model being queried. 183 column : sequence of int 184 The column in the data model being queried. 185 text : str 186 The text to set. 187 188 Raises 189 ------- 190 DataViewSetError 191 If the value cannot be set. 192 """ 193 raise DataViewSetError("Cannot set value.") 194 195 def has_color(self, model, row, column): 196 """ Whether or not the value has color data. 197 198 has_color : bool 199 Whether or not the value has data-associated color 200 values. 201 """ 202 return False 203 204 def get_color(self, model, row, column): 205 """ Get data-associated colour values for the given item. 206 207 The default implementation returns white. 208 209 color : Color instance 210 The color associated with the cell. 211 """ 212 return Color(rgba=(1.0, 1.0, 1.0, 1.0)) 213 214 def has_image(self, model, row, column): 215 """ Whether or not the value has an image associated with it. 216 217 The default implementation returns True if ``get_image`` 218 returns a non-None value. 219 220 Parameters 221 ---------- 222 model : AbstractDataModel 223 The data model holding the data. 224 row : sequence of int 225 The row in the data model being queried. 226 column : sequence of int 227 The column in the data model being queried. 228 229 Returns 230 ------- 231 has_image : bool 232 Whether or not the value has an image associated with it. 233 """ 234 return False 235 236 def get_image(self, model, row, column): 237 """ An image associated with the underlying value. 238 239 The default implementation returns None. 240 241 Parameters 242 ---------- 243 model : AbstractDataModel 244 The data model holding the data. 245 row : sequence of int 246 The row in the data model being queried. 247 column : sequence of int 248 The column in the data model being queried. 249 250 Returns 251 ------- 252 image : IImageResource 253 The image associated with the underlying value. 254 """ 255 from pyface.image_resource import ImageResource 256 return ImageResource("image_not_found") 257 258 def has_check_state(self, model, row, column): 259 """ Whether or not the value has checked state. 260 261 The default implementation returns False. 262 263 Parameters 264 ---------- 265 model : AbstractDataModel 266 The data model holding the data. 267 row : sequence of int 268 The row in the data model being queried. 269 column : sequence of int 270 The column in the data model being queried. 271 272 Returns 273 ------- 274 has_check_state : bool 275 Whether or not the value has a checked state. 276 """ 277 return False 278 279 def get_check_state(self, model, row, column): 280 """ The state of the item check box. 281 282 The default implementation returns "checked" if the value is 283 truthy, or "unchecked" if the value is falsey. 284 285 Parameters 286 ---------- 287 model : AbstractDataModel 288 The data model holding the data. 289 row : sequence of int 290 The row in the data model being queried. 291 column : sequence of int 292 The column in the data model being queried. 293 294 Returns 295 ------- 296 check_state : CheckState 297 The current checked state. 298 """ 299 return ( 300 CheckState.CHECKED 301 if model.get_value(row, column) 302 else CheckState.UNCHECKED 303 ) 304 305 def set_check_state(self, model, row, column, check_state): 306 """ Set the checked state of the underlying value. 307 308 The default implementation does not allow setting the checked state. 309 310 Parameters 311 ---------- 312 model : AbstractDataModel 313 The data model holding the data. 314 row : sequence of int 315 The row in the data model being queried. 316 column : sequence of int 317 The column in the data model being queried. 318 check_state : CheckState 319 The check state value to set. 320 321 Raises 322 ------- 323 DataViewSetError 324 If the value cannot be set. 325 """ 326 raise DataViewSetError("Cannot set check state.") 327 328 def has_tooltip(self, model, row, column): 329 """ Whether or not the value has a tooltip. 330 331 The default implementation returns True if ``get_tooltip`` 332 returns a non-empty value. 333 334 Parameters 335 ---------- 336 model : AbstractDataModel 337 The data model holding the data. 338 row : sequence of int 339 The row in the data model being queried. 340 column : sequence of int 341 The column in the data model being queried. 342 343 Returns 344 ------- 345 has_tooltip : bool 346 Whether or not the value has a textual representation. 347 """ 348 return self.get_tooltip(model, row, column) != "" 349 350 def get_tooltip(self, model, row, column): 351 """ The tooltip for the underlying value. 352 353 The default implementation returns an empty string. 354 355 tooltip : str 356 The textual representation of the underlying value. 357 """ 358 return "" 359 360 @observe('+update_value_type') 361 def update_value_type(self, event=None): 362 """ Fire update event when marked traits change. """ 363 self.updated = True 364