~ubuntu-branches/ubuntu/utopic/python-traitsui/utopic

« back to all changes in this revision

Viewing changes to traitsui/qt4/editor.py

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2011-07-09 13:57:39 UTC
  • Revision ID: james.westby@ubuntu.com-20110709135739-x5u20q86huissmn1
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#------------------------------------------------------------------------------
 
2
# Copyright (c) 2007, Riverbank Computing Limited
 
3
# All rights reserved.
 
4
#
 
5
# This software is provided without warranty under the terms of the BSD license.
 
6
# However, when used with the GPL version of PyQt the additional terms described in the PyQt GPL exception also apply
 
7
 
 
8
#
 
9
# Author: Riverbank Computing Limited
 
10
#------------------------------------------------------------------------------
 
11
 
 
12
""" Defines the base class for PyQt editors.
 
13
"""
 
14
 
 
15
#-------------------------------------------------------------------------------
 
16
#  Imports:
 
17
#-------------------------------------------------------------------------------
 
18
 
 
19
from pyface.qt import QtGui
 
20
 
 
21
from traits.api \
 
22
    import HasTraits, Instance, Str, Callable
 
23
 
 
24
from traitsui.api \
 
25
    import Editor as UIEditor
 
26
 
 
27
from constants \
 
28
    import OKColor, ErrorColor
 
29
 
 
30
#-------------------------------------------------------------------------------
 
31
#  'Editor' class:
 
32
#-------------------------------------------------------------------------------
 
33
 
 
34
class Editor ( UIEditor ):
 
35
    """ Base class for PyQt editors for Traits-based UIs.
 
36
    """
 
37
 
 
38
    def clear_layout(self):
 
39
        """ Delete the contents of a control's layout.
 
40
        """
 
41
        layout = self.control.layout()
 
42
        while True:
 
43
            itm = layout.takeAt(0)
 
44
            if itm is None:
 
45
                break
 
46
 
 
47
            itm.widget().setParent(None)
 
48
 
 
49
    #---------------------------------------------------------------------------
 
50
    #  Handles the 'control' trait being set:
 
51
    #---------------------------------------------------------------------------
 
52
 
 
53
    def _control_changed ( self, control ):
 
54
        """ Handles the **control** trait being set.
 
55
        """
 
56
        # FIXME: Check we actually make use of this.
 
57
        if control is not None:
 
58
            control._editor = self
 
59
 
 
60
    #---------------------------------------------------------------------------
 
61
    #  Assigns focus to the editor's underlying toolkit widget:
 
62
    #---------------------------------------------------------------------------
 
63
 
 
64
    def set_focus ( self ):
 
65
        """ Assigns focus to the editor's underlying toolkit widget.
 
66
        """
 
67
        if self.control is not None:
 
68
            self.control.setFocus()
 
69
 
 
70
    #---------------------------------------------------------------------------
 
71
    #  Updates the editor when the object trait changes external to the editor:
 
72
    #---------------------------------------------------------------------------
 
73
 
 
74
    def update_editor ( self ):
 
75
        """ Updates the editor when the object trait changes externally to the
 
76
            editor.
 
77
        """
 
78
        new_value = self.str_value
 
79
        if self.control.text() != new_value:
 
80
            self.control.setText( new_value )
 
81
 
 
82
    #---------------------------------------------------------------------------
 
83
    #  Handles an error that occurs while setting the object's trait value:
 
84
    #---------------------------------------------------------------------------
 
85
 
 
86
    def error ( self, excp ):
 
87
        """ Handles an error that occurs while setting the object's trait value.
 
88
        """
 
89
        # Make sure the control is a widget rather than a layout.
 
90
        if isinstance(self.control, QtGui.QLayout):
 
91
            control = self.control.parentWidget()
 
92
        else:
 
93
            control = self.control
 
94
 
 
95
        QtGui.QMessageBox.information(control,
 
96
                self.description + ' value error', str(excp))
 
97
 
 
98
    #---------------------------------------------------------------------------
 
99
    #  Sets the tooltip for a specified control:
 
100
    #---------------------------------------------------------------------------
 
101
 
 
102
    def set_tooltip ( self, control = None ):
 
103
        """ Sets the tooltip for a specified control.
 
104
        """
 
105
        desc = self.description
 
106
        if desc == '':
 
107
            desc = self.object.base_trait( self.name ).desc
 
108
            if desc is None:
 
109
                return False
 
110
 
 
111
            desc = 'Specifies ' + desc
 
112
 
 
113
        if control is None:
 
114
            control = self.control
 
115
 
 
116
        control.setToolTip( desc )
 
117
 
 
118
        return True
 
119
 
 
120
    #---------------------------------------------------------------------------
 
121
    #  Handles the 'enabled' state of the editor being changed:
 
122
    #---------------------------------------------------------------------------
 
123
 
 
124
    def _enabled_changed(self, enabled):
 
125
        """Handles the **enabled** state of the editor being changed.
 
126
        """
 
127
        if self.control is not None:
 
128
            self._enabled_changed_helper(self.control, enabled)
 
129
 
 
130
    def _enabled_changed_helper(self, control, enabled):
 
131
        """A helper that allows the control to be a layout and recursively
 
132
           manages all its widgets.
 
133
        """
 
134
        if isinstance(control, QtGui.QWidget):
 
135
            control.setEnabled(enabled)
 
136
        else:
 
137
            for i in range(control.count()):
 
138
                itm = control.itemAt(i)
 
139
                self._enabled_changed_helper((itm.widget() or itm.layout()),
 
140
                        enabled)
 
141
 
 
142
    #---------------------------------------------------------------------------
 
143
    #  Handles the 'visible' state of the editor being changed:
 
144
    #---------------------------------------------------------------------------
 
145
 
 
146
    def _visible_changed(self, visible):
 
147
        """Handles the **visible** state of the editor being changed.
 
148
        """
 
149
        if self.label_control is not None:
 
150
            self.label_control.setVisible(visible)
 
151
 
 
152
        self._visible_changed_helper(self.control, visible)
 
153
 
 
154
        # FIXME: Does PyQt need something similar?
 
155
        # Handle the case where the item whose visibility has changed is a
 
156
        # notebook page:
 
157
        #page      = self.control.GetParent()
 
158
        #page_name = getattr( page, '_page_name', '' )
 
159
        #if page_name != '':
 
160
        #    notebook = page.GetParent()
 
161
        #    for i in range( 0, notebook.GetPageCount() ):
 
162
        #        if notebook.GetPage( i ) is page:
 
163
        #            break
 
164
        #    else:
 
165
        #        i = -1
 
166
 
 
167
        #    if visible:
 
168
        #        if i < 0:
 
169
        #            notebook.AddPage( page, page_name )
 
170
 
 
171
        #    elif i >= 0:
 
172
        #        notebook.RemovePage( i )
 
173
 
 
174
    def _visible_changed_helper(self, control, visible):
 
175
        """A helper that allows the control to be a layout and recursively
 
176
           manages all its widgets.
 
177
        """
 
178
        if isinstance(control, QtGui.QWidget):
 
179
            control.setVisible(visible)
 
180
        else:
 
181
            for i in range(control.count()):
 
182
                itm = control.itemAt(i)
 
183
                self._visible_changed_helper((itm.widget() or itm.layout()),
 
184
                        visible)
 
185
 
 
186
    #---------------------------------------------------------------------------
 
187
    #  Returns the editor's control for indicating error status:
 
188
    #---------------------------------------------------------------------------
 
189
 
 
190
    def get_error_control ( self ):
 
191
        """ Returns the editor's control for indicating error status.
 
192
        """
 
193
        return self.control
 
194
 
 
195
    #---------------------------------------------------------------------------
 
196
    #  Returns whether or not the editor is in an error state:
 
197
    #---------------------------------------------------------------------------
 
198
 
 
199
    def in_error_state ( self ):
 
200
        """ Returns whether or not the editor is in an error state.
 
201
        """
 
202
        return False
 
203
 
 
204
    #---------------------------------------------------------------------------
 
205
    #  Sets the editor's current error state:
 
206
    #---------------------------------------------------------------------------
 
207
 
 
208
    def set_error_state ( self, state = None, control = None ):
 
209
        """ Sets the editor's current error state.
 
210
        """
 
211
        if state is None:
 
212
            state = self.invalid
 
213
        state = state or self.in_error_state()
 
214
 
 
215
        if control is None:
 
216
            control = self.get_error_control()
 
217
 
 
218
        if not isinstance( control, list ):
 
219
            control = [ control ]
 
220
 
 
221
        for item in control:
 
222
            pal = QtGui.QPalette(item.palette())
 
223
 
 
224
            if state:
 
225
                color = ErrorColor
 
226
                if getattr( item, '_ok_color', None ) is None:
 
227
                    item._ok_color = QtGui.QColor(pal.color(QtGui.QPalette.Base))
 
228
            else:
 
229
                color = getattr( item, '_ok_color', OKColor )
 
230
 
 
231
            pal.setColor(QtGui.QPalette.Base, color)
 
232
            item.setPalette(pal)
 
233
 
 
234
    #---------------------------------------------------------------------------
 
235
    #  Handles the editor's invalid state changing:
 
236
    #---------------------------------------------------------------------------
 
237
 
 
238
    def _invalid_changed ( self, state ):
 
239
        """ Handles the editor's invalid state changing.
 
240
        """
 
241
        self.set_error_state()
 
242
 
 
243
#-------------------------------------------------------------------------------
 
244
#  'EditorWithList' class:
 
245
#-------------------------------------------------------------------------------
 
246
 
 
247
class EditorWithList ( Editor ):
 
248
    """ Editor for an object that contains a list.
 
249
    """
 
250
    #---------------------------------------------------------------------------
 
251
    #  Trait definitions:
 
252
    #---------------------------------------------------------------------------
 
253
 
 
254
    # Object containing the list being monitored
 
255
    list_object = Instance( HasTraits )
 
256
 
 
257
    # Name of the monitored trait
 
258
    list_name = Str
 
259
 
 
260
    # Function used to evaluate the current list object value:
 
261
    list_value = Callable
 
262
 
 
263
    #---------------------------------------------------------------------------
 
264
    #  Initializes the object:
 
265
    #---------------------------------------------------------------------------
 
266
 
 
267
    def init ( self, parent ):
 
268
        """ Initializes the object.
 
269
        """
 
270
        factory = self.factory
 
271
        name    = factory.name
 
272
        if name != '':
 
273
            self.list_object, self.list_name, self.list_value = \
 
274
                self.parse_extended_name( name )
 
275
        else:
 
276
            self.list_object, self.list_name = factory, 'values'
 
277
            self.list_value = lambda: factory.values
 
278
 
 
279
        self.list_object.on_trait_change( self._list_updated,
 
280
                                          self.list_name, dispatch = 'ui' )
 
281
 
 
282
        self._list_updated()
 
283
 
 
284
    #---------------------------------------------------------------------------
 
285
    #  Disconnects the listeners set up by the constructor:
 
286
    #---------------------------------------------------------------------------
 
287
 
 
288
    def dispose ( self ):
 
289
        """ Disconnects the listeners set up by the constructor.
 
290
        """
 
291
        self.list_object.on_trait_change( self._list_updated,
 
292
                                          self.list_name, remove = True )
 
293
 
 
294
        super( EditorWithList, self ).dispose()
 
295
 
 
296
    #---------------------------------------------------------------------------
 
297
    #  Handles the monitored trait being updated:
 
298
    #---------------------------------------------------------------------------
 
299
 
 
300
    def _list_updated ( self ):
 
301
        """ Handles the monitored trait being updated.
 
302
        """
 
303
        self.list_updated( self.list_value() )
 
304
 
 
305
    #---------------------------------------------------------------------------
 
306
    #  Handles the monitored list being updated:
 
307
    #---------------------------------------------------------------------------
 
308
 
 
309
    def list_updated ( self, values ):
 
310
        """ Handles the monitored list being updated.
 
311
        """
 
312
        raise NotImplementedError
 
313
 
 
314
#-------------------------------------------------------------------------------
 
315
#  'EditorFromView' class:
 
316
#-------------------------------------------------------------------------------
 
317
 
 
318
class EditorFromView ( Editor ):
 
319
    """ An editor generated from a View object.
 
320
    """
 
321
 
 
322
    #---------------------------------------------------------------------------
 
323
    #  Initializes the object:
 
324
    #---------------------------------------------------------------------------
 
325
 
 
326
    def init ( self, parent ):
 
327
        """ Initializes the object.
 
328
        """
 
329
        self._ui = ui = self.init_ui( parent )
 
330
        if ui.history is None:
 
331
            ui.history = self.ui.history
 
332
 
 
333
        self.control = ui.control
 
334
 
 
335
    #---------------------------------------------------------------------------
 
336
    #  Creates and returns the traits UI defined by this editor:
 
337
    #  (Must be overridden by a subclass):
 
338
    #---------------------------------------------------------------------------
 
339
 
 
340
    def init_ui ( self, parent ):
 
341
        """ Creates and returns the traits UI defined by this editor.
 
342
            (Must be overridden by a subclass).
 
343
        """
 
344
        raise NotImplementedError
 
345
 
 
346
    #---------------------------------------------------------------------------
 
347
    #  Updates the editor when the object trait changes external to the editor:
 
348
    #---------------------------------------------------------------------------
 
349
 
 
350
    def update_editor ( self ):
 
351
        """ Updates the editor when the object trait changes externally to the
 
352
            editor.
 
353
        """
 
354
        # Normally nothing needs to be done here, since it should all be handled
 
355
        # by the editor's internally created traits UI:
 
356
        pass
 
357
 
 
358
    #---------------------------------------------------------------------------
 
359
    #  Dispose of the editor:
 
360
    #---------------------------------------------------------------------------
 
361
 
 
362
    def dispose ( self ):
 
363
        """ Disposes of the editor.
 
364
        """
 
365
        self._ui.dispose()
 
366
 
 
367
        super( EditorFromView, self ).dispose()