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
):
23 Observer
.__init
__(self
, model
)
24 QObject
.__init
__(self
)
30 self
.__model
_to
_view
= {}
31 self
.__view
_to
_model
= {}
34 def SLOT(self
, *args
):
35 '''Default slot to handle all Qt callbacks.
36 This method delegates to callbacks from add_signals.'''
38 widget
= self
.sender()
39 sender
= str(widget
.objectName())
41 if sender
in self
.__callbacks
:
42 self
.__callbacks
[sender
](*args
)
44 elif sender
in self
.__view
_to
_model
:
46 model_param
= self
.__view
_to
_model
[sender
]
47 if isinstance(widget
, QTextEdit
):
48 value
= unicode(widget
.toPlainText())
49 model
.set_param(model_param
, value
,
51 elif isinstance(widget
, QLineEdit
):
52 value
= unicode(widget
.text())
53 model
.set_param(model_param
, value
)
54 elif isinstance(widget
, QCheckBox
):
55 model
.set_param(model_param
, widget
.isChecked())
56 elif isinstance(widget
, QSpinBox
):
57 model
.set_param(model_param
, widget
.value())
58 elif isinstance(widget
, QFontComboBox
):
59 value
= unicode(widget
.currentFont().toString())
60 model
.set_param(model_param
, value
)
61 elif isinstance(widget
, QDateEdit
):
63 value
= str(widget
.date().toString(fmt
))
64 model
.set_param(model_param
, value
)
66 print("SLOT(): Unknown widget:", sender
, widget
)
68 def connect(self
, obj
, signal_str
, *args
):
69 '''Convenience function so that subclasses do not have
70 to import QtCore.SIGNAL.'''
72 if type(signal
) is str:
73 signal
= SIGNAL(signal
)
74 return QObject
.connect(obj
, signal
, *args
)
76 def add_signals(self
, signal_str
, *objects
):
77 '''Connects object's signal to the QObserver.'''
79 self
.connect(obj
, signal_str
, self
.SLOT
)
81 def add_callbacks(self
, **callbacks
):
82 '''Registers callbacks that are called in response to GUI events.'''
83 for sender
, callback
in callbacks
.iteritems():
84 self
.__callbacks
[sender
] = callback
85 self
.autoconnect(getattr(self
.view
, sender
))
87 def add_observables(self
, *params
):
88 '''This method assumes that widgets and model params
89 share the same name.'''
91 self
.model_to_view(param
, getattr(self
.view
, param
))
93 def model_to_view(self
, model_param
, *widgets
):
94 '''Binds model params to qt widgets(model->view)'''
95 self
.__model
_to
_view
[model_param
] = widgets
97 view
= str(w
.objectName())
98 self
.__view
_to
_model
[view
] = model_param
101 def autoconnect(self
, *widgets
):
103 self
.__autoconnect
(w
)
105 def __autoconnect(self
, widget
):
106 '''Automagically connects Qt widgets to QObserver.SLOT'''
108 if widget
in self
.__connected
: return
109 self
.__connected
.append(widget
)
111 if isinstance(widget
, QTextEdit
):
113 'textChanged()', widget
)
114 elif isinstance(widget
, QLineEdit
):
116 'textChanged(const QString&)', widget
)
117 elif isinstance(widget
, QListWidget
):
119 'itemSelectionChanged()', widget
)
121 'itemClicked(QListWidgetItem *)', widget
)
123 'itemDoubleClicked(QListWidgetItem*)', widget
)
124 elif isinstance(widget
, QAbstractButton
):
126 'released()', widget
)
127 elif isinstance(widget
, QAction
):
129 'triggered()', widget
)
130 elif isinstance(widget
, QCheckBox
):
132 'stateChanged(int)', widget
)
133 elif isinstance(widget
, QSpinBox
):
135 'valueChanged(int)', widget
)
136 elif isinstance(widget
, QFontComboBox
):
138 'currentFontChanged(const QFont&)', widget
)
139 elif isinstance(widget
, QSplitter
):
141 'splitterMoved(int,int)', widget
)
142 elif isinstance(widget
, QDateEdit
):
144 'dateChanged(const QDate&)', widget
)
147 "Asked to connect unknown widget:\n\t"
148 "%s => %s" %( type(widget
),
149 str(widget
.objectName()) ))
151 def add_actions(self
, **kwargs
):
152 '''Register view actions that are called in response to
153 view changes.(view->model)'''
154 for model_param
, callback
in kwargs
.iteritems():
155 if type(callback
) is list:
156 self
.__actions
[model_param
] = callback
158 self
.__actions
[model_param
] = [callback
]
160 def subject_changed(self
, param
, value
):
161 '''Sends a model param to the view(model->view)'''
163 if param
in self
.__model
_to
_view
:
164 notify
= self
.model
.get_notify()
165 self
.model
.set_notify(False)
166 for widget
in self
.__model
_to
_view
[param
]:
167 if isinstance(widget
, QSpinBox
):
168 widget
.setValue(value
)
169 elif isinstance(widget
, QPixmap
):
171 elif isinstance(widget
, QTextEdit
):
172 widget
.setText(value
)
173 elif isinstance(widget
, QLineEdit
):
174 widget
.setText(value
)
175 elif isinstance(widget
, QListWidget
):
179 elif isinstance(widget
, QCheckBox
):
180 widget
.setChecked(value
)
181 elif isinstance(widget
, QFontComboBox
):
182 font
= widget
.currentFont()
183 font
.fromString(value
)
184 elif isinstance(widget
, QDateEdit
):
187 date
= QDate
.fromString(value
, fmt
)
191 print('subject_changed(): '
193 str(widget
.objectName()),
195 self
.model
.set_notify(notify
)
197 if param
not in self
.__actions
:
200 if param
in self
.__model
_to
_view
:
201 for widget
in self
.__model
_to
_view
[param
]:
202 widgets
.append(widget
)
203 # Call the model callback w/ the view's widgets as the args
204 for action
in self
.__actions
[param
]:
207 def refresh_view(self
, *params
):
209 params
= tuple(self
.__model
_to
_view
.keys()
210 + self
.__actions
.keys())
213 if param
not in notified
:
214 notified
.append(param
)
215 self
.model
.notify_observers(*notified
)