2 from PyQt4
.QtCore
import Qt
3 from PyQt4
.QtCore
import QObject
4 from PyQt4
.QtCore
import SIGNAL
5 from PyQt4
.QtCore
import QDate
6 from PyQt4
.QtGui
import QDateEdit
7 from PyQt4
.QtGui
import QSpinBox
8 from PyQt4
.QtGui
import QPixmap
9 from PyQt4
.QtGui
import QTextEdit
10 from PyQt4
.QtGui
import QLineEdit
11 from PyQt4
.QtGui
import QListWidget
12 from PyQt4
.QtGui
import QCheckBox
13 from PyQt4
.QtGui
import QFontComboBox
14 from PyQt4
.QtGui
import QAbstractButton
15 from PyQt4
.QtGui
import QSplitter
16 from PyQt4
.QtGui
import QAction
18 from ugit
.observer
import Observer
20 class QObserver(Observer
, QObject
):
22 def __init__(self
, model
, view
, *args
, **kwargs
):
23 Observer
.__init
__(self
, model
)
24 QObject
.__init
__(self
)
30 self
.__model
_to
_view
= {}
31 self
.__view
_to
_model
= {}
33 # Call user-defined startup routine
34 self
.init(model
, view
, *args
, **kwargs
)
36 def init(self
, model
, view
, *args
, **kwargs
):
39 def SLOT(self
, *args
):
40 '''Default slot to handle all Qt callbacks.
41 This method delegates to callbacks from add_signals.'''
43 widget
= self
.sender()
44 sender
= str(widget
.objectName())
46 if sender
in self
.__callbacks
:
47 self
.__callbacks
[sender
](*args
)
49 elif sender
in self
.__view
_to
_model
:
51 model_param
= self
.__view
_to
_model
[sender
]
52 if isinstance(widget
, QTextEdit
):
53 value
= unicode(widget
.toPlainText())
54 model
.set_param(model_param
, value
,
56 elif isinstance(widget
, QLineEdit
):
57 value
= unicode(widget
.text())
58 model
.set_param(model_param
, value
)
59 elif isinstance(widget
, QCheckBox
):
60 model
.set_param(model_param
, widget
.isChecked())
61 elif isinstance(widget
, QSpinBox
):
62 model
.set_param(model_param
, widget
.value())
63 elif isinstance(widget
, QFontComboBox
):
64 value
= unicode(widget
.currentFont().toString())
65 model
.set_param(model_param
, value
)
66 elif isinstance(widget
, QDateEdit
):
68 value
= str(widget
.date().toString(fmt
))
69 model
.set_param(model_param
, value
)
70 elif isinstance(widget
, QListWidget
):
73 print("SLOT(): Unknown widget:", sender
, widget
)
75 def connect(self
, obj
, signal_str
, *args
):
76 '''Convenience function so that subclasses do not have
77 to import QtCore.SIGNAL.'''
79 if type(signal
) is str:
80 signal
= SIGNAL(signal
)
81 return QObject
.connect(obj
, signal
, *args
)
83 def add_signals(self
, signal_str
, *objects
):
84 '''Connects object's signal to the QObserver.'''
86 self
.connect(obj
, signal_str
, self
.SLOT
)
88 def add_callbacks(self
, **callbacks
):
89 '''Registers callbacks that are called in response to GUI events.'''
90 for sender
, callback
in callbacks
.iteritems():
91 self
.__callbacks
[sender
] = callback
92 self
.autoconnect(getattr(self
.view
, sender
))
94 def add_observables(self
, *params
):
95 '''This method assumes that widgets and model params
96 share the same name.'''
98 self
.model_to_view(param
, getattr(self
.view
, param
))
100 def model_to_view(self
, model_param
, *widgets
):
101 '''Binds model params to qt widgets(model->view)'''
102 self
.__model
_to
_view
[model_param
] = widgets
104 view
= str(w
.objectName())
105 self
.__view
_to
_model
[view
] = model_param
106 self
.__autoconnect
(w
)
108 def autoconnect(self
, *widgets
):
110 self
.__autoconnect
(w
)
112 def __autoconnect(self
, widget
):
113 '''Automagically connects Qt widgets to QObserver.SLOT'''
115 if widget
in self
.__connected
: return
116 self
.__connected
.append(widget
)
118 if isinstance(widget
, QTextEdit
):
120 'textChanged()', widget
)
121 elif isinstance(widget
, QLineEdit
):
123 'textChanged(const QString&)', widget
)
124 elif isinstance(widget
, QListWidget
):
126 'itemSelectionChanged()', widget
)
128 'itemClicked(QListWidgetItem *)', widget
)
130 'itemDoubleClicked(QListWidgetItem*)', widget
)
131 elif isinstance(widget
, QAbstractButton
):
133 'released()', widget
)
134 elif isinstance(widget
, QAction
):
136 'triggered()', widget
)
137 elif isinstance(widget
, QCheckBox
):
139 'stateChanged(int)', widget
)
140 elif isinstance(widget
, QSpinBox
):
142 'valueChanged(int)', widget
)
143 elif isinstance(widget
, QFontComboBox
):
145 'currentFontChanged(const QFont&)', widget
)
146 elif isinstance(widget
, QSplitter
):
148 'splitterMoved(int,int)', widget
)
149 elif isinstance(widget
, QDateEdit
):
151 'dateChanged(const QDate&)', widget
)
154 "Asked to connect unknown widget:\n\t"
155 "%s => %s" %( type(widget
),
156 str(widget
.objectName()) ))
158 def add_actions(self
, **kwargs
):
159 '''Register view actions that are called in response to
160 view changes.(view->model)'''
161 for model_param
, callback
in kwargs
.iteritems():
162 if type(callback
) is list:
163 self
.__actions
[model_param
] = callback
165 self
.__actions
[model_param
] = [callback
]
167 def subject_changed(self
, param
, value
):
168 '''Sends a model param to the view(model->view)'''
170 if param
in self
.__model
_to
_view
:
171 notify
= self
.model
.get_notify()
172 self
.model
.set_notify(False)
173 for widget
in self
.__model
_to
_view
[param
]:
174 if isinstance(widget
, QSpinBox
):
175 widget
.setValue(value
)
176 elif isinstance(widget
, QPixmap
):
178 elif isinstance(widget
, QTextEdit
):
179 widget
.setText(value
)
180 elif isinstance(widget
, QLineEdit
):
181 widget
.setText(value
)
182 elif isinstance(widget
, QListWidget
):
186 elif isinstance(widget
, QCheckBox
):
187 widget
.setChecked(value
)
188 elif isinstance(widget
, QFontComboBox
):
189 font
= widget
.currentFont()
190 font
.fromString(value
)
191 elif isinstance(widget
, QDateEdit
):
194 date
= QDate
.fromString(value
, fmt
)
198 print('subject_changed(): '
200 str(widget
.objectName()),
202 self
.model
.set_notify(notify
)
204 if param
not in self
.__actions
:
207 if param
in self
.__model
_to
_view
:
208 for widget
in self
.__model
_to
_view
[param
]:
209 widgets
.append(widget
)
210 # Call the model callback w/ the view's widgets as the args
211 for action
in self
.__actions
[param
]:
214 def refresh_view(self
, *params
):
216 params
= tuple(self
.__model
_to
_view
.keys()
217 + self
.__actions
.keys())
220 if param
not in notified
:
221 notified
.append(param
)
222 self
.model
.notify_observers(*notified
)