2 from PyQt4
.QtCore
import QObject
3 from PyQt4
.QtCore
import SIGNAL
4 from PyQt4
.QtGui
import QSpinBox
5 from PyQt4
.QtGui
import QPixmap
6 from PyQt4
.QtGui
import QTextEdit
7 from PyQt4
.QtGui
import QLineEdit
8 from PyQt4
.QtGui
import QListWidget
9 from PyQt4
.QtGui
import QCheckBox
10 from PyQt4
.QtGui
import QFontComboBox
11 from PyQt4
.QtGui
import QAbstractButton
12 from PyQt4
.QtGui
import QSplitter
13 from PyQt4
.QtGui
import QAction
15 from observer
import Observer
17 class QObserver(Observer
, QObject
):
19 def __init__(self
, model
, view
):
20 Observer
.__init
__(self
, model
)
21 QObject
.__init
__(self
)
27 self
.__model
_to
_view
= {}
28 self
.__view
_to
_model
= {}
31 def SLOT(self
, *args
):
32 '''Default slot to handle all Qt callbacks.
33 This method delegates to callbacks from add_signals.'''
35 widget
= self
.sender()
36 sender
= str(widget
.objectName())
38 if sender
in self
.__callbacks
:
39 self
.__callbacks
[sender
](*args
)
41 elif sender
in self
.__view
_to
_model
:
43 model_param
= self
.__view
_to
_model
[sender
]
44 if isinstance(widget
, QTextEdit
):
45 value
= unicode(widget
.toPlainText())
46 model
.set_param(model_param
, value
,
48 elif isinstance(widget
, QLineEdit
):
49 value
= unicode(widget
.text())
50 model
.set_param(model_param
, value
)
51 elif isinstance(widget
, QCheckBox
):
52 model
.set_param(model_param
, widget
.isChecked())
53 elif isinstance(widget
, QSpinBox
):
54 model
.set_param(model_param
, widget
.value())
55 elif isinstance(widget
, QFontComboBox
):
56 value
= unicode(widget
.currentFont().toString())
57 model
.set_param(model_param
, value
)
59 print("SLOT(): Unknown widget:", sender
, widget
)
61 def connect(self
, obj
, signal_str
, *args
):
62 '''Convenience function so that subclasses do not have
63 to import QtCore.SIGNAL.'''
65 if type(signal
) is str:
66 signal
= SIGNAL(signal
)
67 return QObject
.connect(obj
, signal
, *args
)
69 def add_signals(self
, signal_str
, *objects
):
70 '''Connects object's signal to the QObserver.'''
72 self
.connect(obj
, signal_str
, self
.SLOT
)
74 def add_callbacks(self
, **callbacks
):
75 '''Registers callbacks that are called in response to GUI events.'''
76 for sender
, callback
in callbacks
.iteritems():
77 self
.__callbacks
[sender
] = callback
78 self
.autoconnect(getattr(self
.view
, sender
))
80 def add_observables(self
, *params
):
81 '''This method assumes that widgets and model params
82 share the same name.'''
84 self
.model_to_view(param
, getattr(self
.view
, param
))
86 def model_to_view(self
, model_param
, *widgets
):
87 '''Binds model params to qt widgets(model->view)'''
88 self
.__model
_to
_view
[model_param
] = widgets
90 view
= str(w
.objectName())
91 self
.__view
_to
_model
[view
] = model_param
94 def autoconnect(self
, *widgets
):
98 def __autoconnect(self
, widget
):
99 '''Automagically connects Qt widgets to QObserver.SLOT'''
101 if widget
in self
.__connected
: return
102 self
.__connected
.append(widget
)
104 if isinstance(widget
, QTextEdit
):
106 'textChanged()', widget
)
107 elif isinstance(widget
, QLineEdit
):
109 'textChanged(const QString&)', widget
)
110 elif isinstance(widget
, QListWidget
):
112 'itemSelectionChanged()', widget
)
114 'itemClicked(QListWidgetItem *)', widget
)
116 'itemDoubleClicked(QListWidgetItem*)', widget
)
117 elif isinstance(widget
, QAbstractButton
):
119 'released()', widget
)
120 elif isinstance(widget
, QAction
):
122 'triggered()', widget
)
123 elif isinstance(widget
, QCheckBox
):
125 'stateChanged(int)', widget
)
126 elif isinstance(widget
, QSpinBox
):
128 'valueChanged(int)', widget
)
129 elif isinstance(widget
, QFontComboBox
):
131 'currentFontChanged(const QFont&)', widget
)
132 elif isinstance(widget
, QSplitter
):
134 'splitterMoved(int,int)', widget
)
137 "Asked to connect unknown widget:\n\t"
138 "%s => %s" %( type(widget
),
139 str(widget
.objectName()) ))
141 def add_actions(self
, model_param
, callback
):
142 '''Register view actions that are called in response to
143 view changes.(view->model)'''
144 self
.__actions
[model_param
] = callback
146 def subject_changed(self
, param
, value
):
147 '''Sends a model param to the view(model->view)'''
149 if param
in self
.__model
_to
_view
:
150 notify
= self
.model
.get_notify()
151 self
.model
.set_notify(False)
152 for widget
in self
.__model
_to
_view
[param
]:
153 if isinstance(widget
, QSpinBox
):
154 widget
.setValue(value
)
155 elif isinstance(widget
, QPixmap
):
157 elif isinstance(widget
, QTextEdit
):
158 widget
.setText(value
)
159 elif isinstance(widget
, QLineEdit
):
160 widget
.setText(value
)
161 elif isinstance(widget
, QListWidget
):
163 for i
in value
: widget
.addItem(i
)
164 elif isinstance(widget
, QCheckBox
):
165 widget
.setChecked(value
)
166 elif isinstance(widget
, QFontComboBox
):
167 font
= widget
.currentFont()
168 font
.fromString(value
)
170 print('subject_changed(): '
172 widget_name
, widget
, value
)
173 self
.model
.set_notify(notify
)
175 if param
not in self
.__actions
: return
177 if param
in self
.__model
_to
_view
:
178 for widget
in self
.__model
_to
_view
[param
]:
179 widgets
.append(widget
)
180 # Call the model callback w/ the view's widgets as the args
181 self
.__actions
[param
](*widgets
)
183 def refresh_view(self
):
184 params
= list(self
.__model
_to
_view
.keys()
185 + self
.__actions
.keys())
188 if param
not in notified
:
189 notified
.append(param
)
190 self
.model
.notify_observers(*notified
)