1
2
3
4
5
6
7
8
9
10
11 from twisted.internet import defer, reactor
12
13 from PyQt4.Qt import *
14
15 from mc import MC
16 from util import Util
20
23
25 '''
26 Base screen class, includes common methods used by all screens.
27 '''
29 '''
30 Initializes the mcwindow widget
31 '''
32 self._screenID = Util.uniq()
33 self._modified = False
34 self._mode = None
35
37 '''
38 Sets the icon of the tab widget that includes this screen.
39 '''
40 try:
41 currentTabPage = self.parent().parent()
42 tabWidget = currentTabPage.parent().parent()
43 screenIndex = tabWidget.indexOf(currentTabPage)
44 tabWidget.setTabIcon(screenIndex, QIcon(iconPath))
45 except AttributeError:
46 pass
47
49 '''
50 Sets the screen mode
51 '''
52 self._mode = mode
53
55 '''
56 Returns the screen mode
57 '''
58 return self._mode
59
61 '''
62 Returns the unique id of this screen.
63 '''
64 return self._screenID
65
67 '''
68 Find and return reference for a screen represented by screen ID
69 screenID. Search will be made starting from rootObj.
70
71 @param rootObj: Root of search
72 @type rootObj: QWidget
73 @param screenID: Unique id of screen
74 @type screenID: str
75 @return: Screen having screen id of screenID, None if not found
76 '''
77 for obj in rootObj.findChildren(MCScreen):
78 if obj.screenID() == screenID:
79 return obj
80
81 return None
82
84 '''
85 Gets the class for a given screen defined by screenPath.
86
87 @param screenPath: Path defining the screen
88 @type screenPath: str
89 @return: A class object for the screen
90 '''
91 return _parent().getScreenClass(screenPath)
92
94 '''
95 Disables screen visual updates.
96 '''
97 self.setUpdatesEnabled(False)
98 self.setDisabled(True)
99
101 '''
102 Enables screen visual updates.
103 '''
104 self.setEnabled(True)
105 self.setUpdatesEnabled(True)
106
107 @defer.inlineCallbacks
109 '''
110 Sets the screen as busy, screen is disabled after this call
111
112 @param changeIcon: If True, the default, sets a busy icon in the
113 related tab for this screen.
114 @type changeIcon: bool
115 '''
116 if remoteCallActive:
117 MC.MAIN_WINDOW.incRemoteCallCount()
118 self.setScreenIcon(':/icons/busy.png')
119
120
121 yield Util.deferredSleep(0.01)
122
123 self.setScreenDisabled()
124
125 @defer.inlineCallbacks
141
142 @defer.inlineCallbacks
143 - def execute(self, taskPath, *prm, **kw):
144 '''
145 Executes the given remote code on the server. Returns the result of the call.
146
147 @type taskPath: C{string}
148 @param taskPath: Remote code location in distribution hierarchy,
149 i.e. "mcbase.controllers.perform.SampleClass:run"
150 @param args: Remote call parameters
151 @param kw: Remote call keyword parameters
152 @return: Result of the remote execution
153 '''
154 yield self.setScreenBusy()
155
156
157 try:
158 result = yield _client().execute(taskPath, *prm, **kw)
159 yield self.setScreenAvailable()
160 except Exception, e:
161 print '*** ERROR in execute:', e
162 yield self.setScreenAvailable()
163
164 raise e
165
166 defer.returnValue(result)
167
168 @defer.inlineCallbacks
170 '''
171 Gets mobile code from the remote server according to the given codePath
172
173 @type codePath: C{string}
174 @param codePath: String representing the code path to be transferred
175 '''
176 yield self.setScreenBusy()
177
178
179 try:
180 yield _client().getRemoteCode(codePath)
181 yield self.setScreenAvailable()
182 except:
183 yield self.setScreenAvailable()
184
185 raise
186
187 @defer.inlineCallbacks
188 - def sendMsg(self, taskPath, *prm, **kw):
189 '''
190 Sends the given message to other clients under this user's domain.
191 Executes the given remote code on the server. Returns the result of the call.
192
193 @type taskPath: C{string}
194 @param taskPath: Message identifier, should be similar to 'a.b.c'
195 @param args: Message parameters
196 @param kw: Message keyword parameters
197 '''
198 yield _client().sendMsg(taskPath, *prm, **kw)
199
201 '''
202 Automatically prepares the screen fields according to given class(es).
203 Class <-> Field matching is done by looking at field's object names.
204
205 @param classes: Arbitrary number of classes whose metadata will be
206 used to prepare the screen fields.
207 '''
208 for classObj in classes:
209
210 candidateWidgets = self.findChildren(QWidget, QRegExp('^%s_.*' % classObj.__name__, Qt.CaseInsensitive))
211
212 for widget in candidateWidgets:
213 widget.applyModelConstraints(classObj)
214
216 '''
217 Automatically fills the screen fields according to given instance.
218 Instance <-> Field matching is done by looking at field's object names.
219
220 @param instance: Instance whose metadata will be used to fill the
221 related fields on the screen.
222 '''
223
224 candidateWidgets = self.findChildren(QWidget, QRegExp('^%s_.*' % instance.__class__.__name__, Qt.CaseInsensitive))
225
226 for widget in candidateWidgets:
227 widget.set(getattr(instance, '_'.join(str(widget.objectName()).split('_')[1:])))
228
230 '''
231 Automatically creates an object of class C{class} and assigns attributes
232 using on screen information. Widget object names are used to discover
233 class name and attributes.
234
235 @param klass: Class whose metadata will be used to create a model
236 object.
237 @returns: Newly created object
238 '''
239 newObject = klass()
240
241 candidateWidgets = self.findChildren(QWidget, QRegExp('^%s_.*' % klass.__name__, Qt.CaseInsensitive))
242
243 for widget in candidateWidgets:
244 setattr(newObject, '_'.join(str(widget.objectName()).split('_')[1:]), widget.get())
245
246 return newObject
247
249 '''
250 Automatically updates an object C{obj} and assigns attributes using on
251 screen information. Widget object names are used to discover class name
252 and attributes.
253
254 @param obj: Object which will be updated using on screen information
255 @returns: Updated object
256 '''
257
258 candidateWidgets = self.findChildren(QWidget, QRegExp('^%s_.*' % obj.__class__.__name__, Qt.CaseInsensitive))
259
260 for widget in candidateWidgets:
261 setattr(obj, '_'.join(str(widget.objectName()).split('_')[1:]), widget.get())
262
263 return obj
264
267
270
271 @defer.inlineCallbacks
273 '''
274 Instructs the main window to close this screen. Any result is passed
275 to main window.
276 '''
277 yield self.setScreenBusy(remoteCallActive=False)
278 reactor.callLater(0.01, MC.MAIN_WINDOW.closeScreen, self.screenID())
279
280 self.emit(SIGNAL('screenClosed(PyQt_PyObject)'), result)
281
282 - def errorDialog(self, caption=tr('Error'), shortMsg='', longMsg=''):
284