1 """
2 """
3
4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
6
7 import re
8
9 import Connection
10 import Constants
11 import Dock.Plotting
12 import Dock.LinearAlgebra
13 import Dock.Transforms
14 import Dock.Cosmology
15 import Dock.GeneralFunctions
16 import Dock.Statistics
17 import Dock.StellarDynamics
18 import Preferences
19 import RemoteFile
20
21
23 """
24 Overview
25 ========
26 This class holds virtually all of the QAction's that the client will perform. That is not to say it holds
27 all of the functionality, but rather the middleman to the functionality. These actions define what happens
28 when they are activated, and then other things like buttons use a QAction to actually do something useful.
29
30 Every action in the menu bar is contained here. They exist here and not in the menu class because other
31 things, such as the tool bar also use them. They are grouped according to package/section in a python list.
32 This is so that other objects can unroll the entire list and get all of the actions at once.
33
34 If you are adding an action to an existing package, then its as easy as copying a previous entry. It will be
35 propogated through the entire program from here.
36
37 Packages are a tad trickier to implement, but not that much. You can mimic the way they are laid out here,
38 however, objects like the tool/menu bar will need to be aware the new package exists. See the individual
39 object's class for details.
40 """
41
43 """
44 Overview
45 ========
46 This initialization method takes only the bridge to
47 set up its interconnectivity. Other than that it is
48 simply setting up lists of QActions and Actions.
49
50 QActions are used for non-dock related actions. This
51 is for things like open/save which are independant.
52
53 Actions are used for dock related actions. They handle
54 some of the hiding/showing of the widget as well as
55 enabling/disabling the action when its in use.
56
57 It looks painful looking at all of the definitions in here,
58 however they get propogated everywhere else, so a little
59 pain here helps the other widgets that need these actions
60 defined.
61
62 @param bridge: The bridge object which connects all interactive components together.
63 @type bridge: L{Bridge<client.Bridge.Bridge>}
64 """
65
66 self._bridge = bridge
67 bridge.setActions (self)
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 self._file = []
84
85 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/connect.png"), "Connect", None))
86 self._file[-1].setStatusTip ("Allows you to connect to your cluster")
87 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.connect)
88 self._file[-1].setShortcut ("Ctrl+c")
89
90 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/disconnect.png"), "Disconnect", None))
91 self._file[-1].setStatusTip ("Disconnects you from the cluster")
92 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.disconnect)
93 self._file[-1].setShortcut ("Ctrl+d")
94
95 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/update.png"), "Update", None))
96 self._file[-1].setStatusTip ("Updates the interface for all changes that may have occurred")
97 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self._bridge.Update)
98
99 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/open.png"), "Open", None))
100 self._file[-1].setStatusTip ("Open a data data file to a region")
101 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.importFile)
102
103 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/save.png"), "Save", None))
104 self._file[-1].setEnabled (False)
105 self._file[-1].setStatusTip ("Save a region to a file")
106 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.exportFile)
107
108 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/python.png"), "Save IPython Log", None))
109 self._file[-1].setStatusTip ("Save your IPython's session log to Html or Text")
110 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self._bridge.SaveIPythonSession)
111
112 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/savebatch.png"), "Save Batch File", None))
113 self._file[-1].setStatusTip ("Save commands you've issued to a batch file to redo later")
114 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.saveBatch)
115
116 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/loadbatch.png"), "Load Batch File", None))
117 self._file[-1].setStatusTip ("Loads a batch file and executes all of its commands")
118 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.loadBatch)
119
120 self._file.append (QAction (QIcon (Constants.ICON_DIR + "/file/preferences.png"), "Preferences", None))
121 self._file[-1].setStatusTip ("Brings up dialog for changing basin_client settings")
122 QObject.connect (self._file[-1], SIGNAL ("triggered ()"), self.preferences)
123
124
125
126
127
128
129
130
131 self._genf = []
132
133 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/random.png"), \
134 QString ("Random Attribute"), bridge))
135 self._genf[-1].setStatusTip ("Generates a random atribute of any given size")
136 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.AttributeRandom)
137
138 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/constant.png"), \
139 QString ("Constant Attribute"), bridge))
140 self._genf[-1].setStatusTip ("Generates an atribute, filled with a constant, of any given size")
141 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.AttributeConstant)
142
143 self._genf.append (Action (QIcon (Constants.ICON_DEFAULT), \
144 QString ("Attribute Index"), bridge))
145 self._genf[-1].setStatusTip ("Generates an attribute of indicies into your input data")
146 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.AttributeIndex)
147
148 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/real.png"), \
149 "Real", bridge))
150 self._genf[-1].setStatusTip ("Retrieves an attribute's real part")
151 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Real)
152
153 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/imaginary.png"), \
154 "Imaginary", bridge))
155 self._genf[-1].setStatusTip ("Retrieves an attribute's imaginary part")
156 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Imaginary)
157
158 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/sort.png"), "Sort", bridge))
159 self._genf[-1].setStatusTip ("Sorts an attribute")
160 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Sort)
161
162 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/sortindex.png"), \
163 "Index Sort", bridge))
164 self._genf[-1].setStatusTip ("Sorts an attribute by index")
165 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.IndexSort)
166
167 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/absval.png"), \
168 "Absolute Value", bridge))
169 self._genf[-1].setStatusTip ("Takes the absolute value of an attribute")
170 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), \
171 self._bridge._dock.AbsoluteValue)
172
173 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/pow.png"), \
174 "Power", bridge))
175 self._genf[-1].setStatusTip ("Takes an attribute to the nth power")
176 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Pow)
177
178 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/squareroot.png"), \
179 QString ("Square Root"), bridge))
180 self._genf[-1].setStatusTip ("Takes an attribute's square root")
181 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.SquareRoot)
182
183 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/log.png"), \
184 QString ("log"), bridge))
185 self._genf[-1].setStatusTip ("Takes the natural log of the attribute")
186 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Log)
187
188 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/log10.png"), \
189 QString ("log10"), bridge))
190 self._genf[-1].setStatusTip ("Takes log base 10 of an attribute")
191 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Log10)
192
193 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/exp.png"), \
194 QString ("exp"), bridge))
195 self._genf[-1].setStatusTip ("Takes an attribute as the power of e")
196 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Exp)
197
198 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/exp10.png"), \
199 QString ("exp10"), bridge))
200 self._genf[-1].setStatusTip ("Takes an attribute as the power of 10")
201 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Exp10)
202
203 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/sin.png"), \
204 QString ("sin"), bridge))
205 self._genf[-1].setStatusTip ("Takes an attribute's sin")
206 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Sin)
207
208 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/cos.png"), \
209 QString ("cos"), bridge))
210 self._genf[-1].setStatusTip ("Takes an attribute's cos")
211 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Cos)
212
213 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/cosh.png"), \
214 QString ("cosh"), bridge))
215 self._genf[-1].setStatusTip ("Takes an attribute's cosh")
216 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Cosh)
217
218 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/sinh.png"), \
219 QString ("sinh"), bridge))
220 self._genf[-1].setStatusTip ("Takes an attribute's sinh")
221 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Sinh)
222
223 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/arccos.png"), \
224 QString ("acos"), bridge))
225 self._genf[-1].setStatusTip ("Takes an attribute's acos")
226 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Acos)
227
228 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/arcsin.png"), \
229 QString ("asin"), bridge))
230 self._genf[-1].setStatusTip ("Takes an attribute's asin")
231 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Asin)
232
233 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/acosh.png"), \
234 QString ("acosh"), bridge))
235 self._genf[-1].setStatusTip ("Takes an attribute's acosh")
236 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Acosh)
237
238 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/asinh.png"), \
239 QString ("asinh"), bridge))
240 self._genf[-1].setStatusTip ("Takes an attribute's asinh")
241 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Asinh)
242
243 self._genf.append (Action (QIcon (Constants.ICON_DIR + "/general_functions/atan.png"), \
244 QString ("atan"), bridge))
245 self._genf[-1].setStatusTip ("Takes an attribute's atan")
246 QObject.connect (self._genf[-1], SIGNAL ("triggered ()"), self._bridge._dock.Atan)
247
248
249
250
251
252
253
254
255 self._plot = []
256
257 self._plot.append (Action (QIcon (Constants.ICON_DIR + "/plotting/plot.png"), \
258 QString ("Gnuplot"), bridge))
259 self._plot[-1].setStatusTip ("Shows the dialog for plotting in Gnuplot")
260 QObject.connect (self._plot[-1], SIGNAL ("triggered ()"), \
261 self._bridge._dock.Gnuplot)
262
263 self._plot.append (Action (QIcon (Constants.ICON_DIR + "/plotting/visit.png"), \
264 QString ("VisIt Plot"), bridge))
265 self._plot[-1].setStatusTip ("Shows the dialog for plotting in VisIt")
266 QObject.connect (self._plot[-1], SIGNAL ("triggered ()"), \
267 self._bridge._dock.VisIt)
268
269 self._plot.append (Action (QIcon (Constants.ICON_DEFAULT), \
270 QString ("PyLab"), bridge))
271 self._plot[-1].setStatusTip ("Shows the dialog for plotting in PyLab")
272 QObject.connect (self._plot[-1], SIGNAL ("triggered ()"), \
273 self._bridge._dock.PyLab)
274
275
276
277
278
279
280
281
282 self._cosm = []
283
284 self._cosm.append (Action (QIcon (Constants.ICON_DIR + "/cosmology/rdist.png"), \
285 QString ("Redshift To Distance"), bridge))
286 self._cosm[-1].setStatusTip ("Shows the dialog for " + \
287 "performing Redshift To Distance")
288 QObject.connect (self._cosm[-1], SIGNAL ("triggered ()"), \
289 self._bridge._dock.RedshiftToDistance)
290
291 self._cosm.append (Action (QIcon (Constants.ICON_DIR + "/cosmology/rgrowth.png"), \
292 QString ("Redshift To Growth"), bridge))
293 self._cosm[-1].setStatusTip ("Shows the dialog for performing Redshift To Growth")
294 QObject.connect (self._cosm[-1], SIGNAL ("triggered ()"), \
295 self._bridge._dock.RedshiftToGrowth)
296
297 self._cosm.append (Action (QIcon (Constants.ICON_DIR + "/cosmology/hubble.png"), \
298 QString ("Hubble Constant"), bridge))
299 self._cosm[-1].setStatusTip ("Shows the dialog for getting the Hubble Constant")
300 QObject.connect (self._cosm[-1], SIGNAL ("triggered ()"), self._bridge._dock.Hubble)
301
302
303
304
305
306
307
308
309 self._stel = []
310
311 self._stel.append (Action (QIcon (Constants.ICON_DIR + "/stellar_dynamics/centerofmass.png"), \
312 QString ("Center Of Mass"), bridge))
313 self._stel[-1].setStatusTip ("Shows the dialog for getting a center of mass")
314 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.CenterOfMass)
315
316 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
317 QString ("Local Density"), bridge))
318 self._stel[-1].setStatusTip ("Shows the dialog for getting the local density")
319 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.LocalDensity)
320
321 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
322 QString ("Density List"), bridge))
323 self._stel[-1].setStatusTip ("Shows the dialog for getting the density list")
324 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.DensityList)
325
326 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
327 QString ("Density Center"), bridge))
328 self._stel[-1].setStatusTip ("Shows the dialog for getting the density's center")
329 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.DensityCenter)
330
331 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
332 QString ("Radial Profile"), bridge))
333 self._stel[-1].setStatusTip ("Shows the dialog for getting a radial profile")
334 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.RadialProfile)
335
336 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
337 QString ("Density Profile"), bridge))
338 self._stel[-1].setStatusTip ("Shows the dialog for getting a density profile")
339 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.DensityProfile)
340
341 self._stel.append (Action (QIcon (Constants.ICON_DEFAULT), \
342 QString ("Disp Profile"), bridge))
343 self._stel[-1].setStatusTip ("Shows the dialog for getting a disp profile")
344 QObject.connect (self._stel[-1], SIGNAL ("triggered ()"), self._bridge._dock.DispProfile)
345
346
347
348
349
350
351
352
353
354 self._stat = []
355
356 self._stat.append (Action (QIcon (Constants.ICON_DIR + "/statistics/mean.png"), \
357 QString ("Mean"), bridge))
358 self._stat[-1].setStatusTip ("Shows the dialog for getting the mean")
359 QObject.connect (self._stat[-1], SIGNAL ("triggered ()"), \
360 self._bridge._dock.Mean)
361
362 self._stat.append (Action (QIcon (Constants.ICON_DIR + "/statistics/stddev.png"), \
363 QString ("Standard Deviation"), bridge))
364 self._stat[-1].setStatusTip ("Shows the dialog for getting " + \
365 "the standard deviation")
366 QObject.connect (self._stat[-1], SIGNAL ("triggered ()"), \
367 self._bridge._dock.StandardDeviation)
368
369 self._stat.append (Action (QIcon (Constants.ICON_DIR + "/statistics/histogram.png"), \
370 QString ("Histogram"), bridge))
371 self._stat[-1].setStatusTip ("Shows the dialog for getting " + \
372 "a histogram's data")
373 QObject.connect (self._stat[-1], SIGNAL ("triggered ()"), \
374 self._bridge._dock.Histogram)
375
376
377
378
379
380
381
382
383 self._tran = []
384
385 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/etoc.png"), \
386 QString ("Equatorial To Cartesian"), bridge))
387 self._tran[-1].setStatusTip ("Shows the dialog for an equatorial to cartesian transformation")
388 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.EquatorialToXyz)
389
390 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/ctoe.png"), \
391 QString ("Cartesian To Equatorial"), bridge))
392 self._tran[-1].setStatusTip ("Shows the dialog for an cartesian to equatorial transformation")
393 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.XyzToEquatorial)
394
395 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/ptoc.png"), \
396 QString ("Polar To Cartesian"), bridge))
397 self._tran[-1].setStatusTip ("Shows the dialog for an polar to cartesian transformation")
398 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.PolarToXy)
399
400 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/ctop.png"), \
401 QString ("Cartesian To Polar"), bridge))
402 self._tran[-1].setStatusTip ("Shows the dialog for an cartesian to polar transformation")
403 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.XyToPolar)
404
405 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/stoc.png"), \
406 QString ("Spherical To Cartesian"), bridge))
407 self._tran[-1].setStatusTip ("Shows the dialog for an spherical to cartesian transformation")
408 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.SphericalToXyz)
409
410 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/ctos.png"), \
411 QString ("Cartesian To Spherical"), bridge))
412 self._tran[-1].setStatusTip ("Shows the idialog for an cartesian to spherical transformation")
413 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.XyzToSpherical)
414
415 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/cytoc.png"), \
416 QString ("Cylindrical To Cartesian"), bridge))
417 self._tran[-1].setStatusTip ("Shows the dialog for an cylindrical to cartesian transformation")
418 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.CylindricalToXyz)
419
420 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/ctocy.png"), \
421 QString ("Cartesian To Cylindrical"), bridge))
422 self._tran[-1].setStatusTip ("Shows the dialog for an cartesian to cylindrical transformation")
423 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.XyzToCylindrical)
424
425 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/fft.png"), \
426 QString ("FFT"), bridge))
427 self._tran[-1].setStatusTip ("Shows the dialog for FFT transformations")
428 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.Fft)
429
430 self._tran.append (Action (QIcon (Constants.ICON_DIR + "/transformations/convolve.png"), \
431 QString ("Convolve"), bridge))
432 self._tran[-1].setStatusTip ("Shows the dialog for an convolving")
433 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.Convolve)
434
435 self._tran.append (Action (QIcon (QString (Constants.ICON_DIR + "/transformations/compdens.png")), \
436 QString ("Compute Density"), bridge))
437 self._tran[-1].setStatusTip ("Shows the dialog for computing density")
438 QObject.connect (self._tran[-1], SIGNAL ("triggered ()"), self._bridge._dock.ComputeDensity)
439
440
441
442
443
444
445
446
447 self._linalg = []
448
449 self._linalg.append (Action (QIcon (Constants.ICON_DIR + "/linear_algebra/matrixcreate.png"), \
450 "Create Matrix", bridge))
451 self._linalg[-1].setStatusTip ("Shows the dialog for creating a matrix")
452 QObject.connect (self._linalg[-1], SIGNAL ("triggered ()"), self._bridge._dock.MatrixCreate)
453
454 self._linalg.append (Action (QIcon (Constants.ICON_DIR + "/linear_algebra/identitymatrixcreate.png"), \
455 "Create Identity Matrix", bridge))
456 self._linalg[-1].setStatusTip ("Shows the dialog for creating an identity matrix")
457 QObject.connect (self._linalg[-1], SIGNAL ("triggered ()"), self._bridge._dock.MatrixCreateIdentity)
458
459 self._linalg.append (Action (QIcon (Constants.ICON_DIR + "/linear_algebra/matrixinvert.png"), \
460 "Invert Matrix", bridge))
461 self._linalg[-1].setStatusTip ("Shows the dialog for inverting a matrix")
462 QObject.connect (self._linalg[-1], SIGNAL ("triggered ()"), self._bridge._dock.MatrixInvert)
463
464 self._linalg.append (Action (QIcon (Constants.ICON_DIR + "/linear_algebra/matrixmult.png"), \
465 "Multiply Matrix", bridge))
466 self._linalg[-1].setStatusTip ("Shows the dialog for multilying matrices")
467 QObject.connect (self._linalg[-1], SIGNAL ("triggered ()"), self._bridge._dock.MatrixMult)
468
469
470
471
472
473
474
475
476 self._help = []
477
478 self._help.append (QAction (QIcon (Constants.ICON_DIR + "/basin.png"), "About", None))
479 self._help[-1].setStatusTip ("Provides general information regarding BASIN")
480 QObject.connect (self._help[-1], SIGNAL ("triggered ()"), self.helpAbout)
481
482 self._help.append (QAction (QIcon (Constants.ICON_DIR + "/help/wiki.png"), "Wiki", None))
483 self._help[-1].setStatusTip ("Provides URL's for BASIN's wiki")
484 QObject.connect (self._help[-1], SIGNAL ("triggered ()"), self.helpWiki)
485
487 """
488 Overview
489 ========
490 This method will enable or disable actions depending on whether they should be used if you are
491 connected. This, of course, gets called whenever your connectivity changes. You can, though
492 you shouldn't, add any dock-related widgets to this method.
493 """
494
495 for act in self._file:
496 if str (act.text ()) == "Connect":
497 act.setEnabled (False)
498 elif str (act.text ()) == "Disconnect":
499 act.setEnabled (True)
500 elif str (act.text ()) == "Open":
501 act.setEnabled (True)
502 elif str (act.text ()) == "Save IPython Log":
503 act.setEnabled (True)
504 elif str (act.text ()) == "Update":
505 act.setEnabled (True)
506 elif str (act.text ()) == "Save Batch File":
507 act.setEnabled (True)
508 elif str (act.text ()) == "Load Batch File":
509 act.setEnabled (True)
510
512 """
513 Overview
514 ========
515 This argument-less method will enable/disable
516 actions depending on whether they should be used
517 if you are disconnected. This, of course, gets
518 called whenever your connectivity changes. You
519 can, though you shouldn't, add any dock-related
520 widgets to this method.
521 """
522
523 for act in self._file:
524 if str (act.text ()) == "Connect":
525 act.setEnabled (True)
526 elif str (act.text ()) == "Disconnect":
527 act.setEnabled (False)
528 elif str (act.text ()) == "Open":
529 act.setEnabled (False)
530 elif str (act.text ()) == "Save IPython Log":
531 act.setEnabled (False)
532 elif str (act.text ()) == "Update":
533 act.setEnabled (False)
534 elif str (act.text ()) == "Save Batch File":
535 act.setEnabled (False)
536 elif str (act.text ()) == "Load Batch File":
537 act.setEnabled (False)
538
540 """
541 Overview
542 ========
543 Assuming everything is connected and parallel, this will enable the Save Action. Presumably
544 this is only called when you click on a Region in the RegionViewer.
545 """
546
547 if self._bridge._connected and self._bridge._parallel:
548 for act in self._file:
549 if str (act.text ()) == "Save":
550 act.setEnabled (True)
551
553 """
554 Overview
555 ========
556 Assuming everything is connected and parallel, this will disable the Save Action. Presumably
557 this is only called when you click on a non-Region in the RegionViewer.
558 """
559
560 for act in self._file:
561 if str (act.text ()) == "Save":
562 act.setEnabled (False)
563
565 """
566 Overview
567 ========
568 This will create an instance of the RemoteFileBrowser. After it is done, it will retrieve the
569 finalresult from the RemoteFileBrowser, and if one actually exists it will create an ipython
570 statement that will go ahead and open up the file.
571
572 This is where the naming convention of reg# is generated. It does this by getting a list of all
573 the top-level regions and it starts counting from reg0 up, and as soon as it finds a name not
574 being used, it takes it.
575
576 One should always remember that the filename retrieved will be one on the remote host, and that
577 the Region constructor in basin_remote handles which BASIN_IO sub-class to use to open the file,
578 so this doesn't need to.
579 """
580
581
582
583 dialog = RemoteFile.RemoteFileBrowser (self._bridge)
584 for file in dialog.finalresult:
585
586 topRegions = self._bridge._ipyShell.getTopLevelRegions ()
587 count = 0
588 var = "reg" + str (count)
589 while topRegions.count (var) > 0:
590 count += 1
591 var = "reg" + str (count)
592
593
594 self._bridge.CursorBusy ()
595 self._bridge._ipyShell.Command (str (var) + " = Region (\"" + str (file) + "\")")
596 self._bridge.CursorNorm ()
597
598
600 """
601 Overview
602 ========
603 This will create an instance of the RemoteFileBrowserExport. After it is done, it will retrieve
604 the finalresult from the RemoteFileBrowser, and if one actually exists it will create an ipython
605 statement that will go ahead and save up the file.
606
607 Unlike opening files, saving them requires knowledge as to what format you want. It is here
608 that you will need to decide what format to use. I use regular expressions to determine if
609 the filename chosen works with our formats to figure out what to save it as.
610
611 Note that there is already a mechanism to stop users from opening this until they have selected
612 a Region, however, this will also safeguard against users from saving non-regions.
613 """
614
615 region = self._bridge._regionViewer.getSingleSelectedItem ()
616 if region != None and region.Type () == "REGION":
617 dialog = RemoteFile.RemoteFileBrowserExport (self._bridge)
618 file = dialog.finalresult[0]
619 if re.compile (".*\.h5").match (str (file)):
620 self._bridge.CursorBusy ()
621 self._bridge._ipyShell.Command (str (region._shellAccess) + \
622 ".SaveHDF5 (\"" + file + "\")")
623 self._bridge.CursorNorm ()
624 elif re.compile (".*\.(dat|txt)").match (str (file)):
625 self._bridge.CursorBusy ()
626 self._bridge._ipyShell.Command (str (region._shellAccess) + \
627 ".SaveTEXT (\"" + file + "\")")
628 self._bridge.CursorNorm ()
629 else:
630 self._bridge._statusBar.showTimed ("You may only export Regions!", STATUS_WAIT)
631
633 """
634 Overview
635 ========
636 Saving a batch is a mildy complicated process because the idea is to save the commands from
637 the entire session, not just while a single user was connected to a connection. This makes it
638 so that whenever any command from the ipython shell is entered, it is likely also sent to an
639 ipython server script that saves it to the server's drive. Thus, to save a batch, this server
640 buffer file must be read, which is what is done here.
641
642 After the server's buffer history is read, it is stored and sent to the BatchSave class which
643 will display a dialog which aids the user in selecting/deselecting which commands to keep and
644 which to throw out. The BatchSave class also handles the actual file io of saving the newly
645 created batch file.
646
647 Please note that a batch file is nothing more than a clear text file of ipython commands, except
648 the first line is a number, the number of lines to read. Also note that like any interactive
649 python session, when you enter multiple line constructs, an extra newline is reuqired to end the
650 construct, and this line counts towards the top number.
651 """
652
653
654
655 if len (self._bridge._ipyShell._commandLine._multiLineHistoryBuffer) > 0:
656 self._bridge._ipyShell.Command ("")
657
658 history = self._bridge._ipyShell.ControllerCommand ("buffer_history.read ()")
659 if history.find ("rror") != -1:
660 self._bridge.Error ("BASIN_actions.py", \
661 "BasinActions", "saveBatch", history)
662
663
664
665 history = history.split ("\n")[4:]
666 if history == []: return
667
668 BatchSave (self._bridge, history)
669
671 """
672 Overview
673 ========
674 This method will use the QFileDialog widget from Qt to open up the batch file. Once a file has
675 been chosen, it will read the first line, the total number of lines to process. Originally this
676 was to make a progresbar, which calculates its percentage from number completed out of total
677 things. I never got around to doing this, so if you're interested look up the class QProgressBar.
678
679 After that, it reads every line thereafter and executes it. This was written before my
680 IpythonView's BatchCommands was written, so this could likely be written slightly more concisely
681 with that, but this should suffice either way.
682 """
683
684 dialog = QFileDialog (None, QString ("Load Script"),
685 QString (str (QDir.home ().path ())),
686 QString ("BASIN Script (*.ipy)"))
687 dialog.setWindowIcon (QIcon (QString (Constants.ICON_DIR + "/file/loadbatch.png")))
688 dialog.setViewMode (QFileDialog.Detail)
689 dialog.setFileMode (QFileDialog.ExistingFile)
690 dialog.setAcceptMode (QFileDialog.AcceptOpen)
691 dialog.exec_ ()
692
693 files = dialog.selectedFiles ()
694 if not files.isEmpty () and dialog.result () == 1:
695 file = QFile (str (files[0]))
696 file.open (QFile.ReadOnly)
697 stream = QTextStream (file)
698
699 commands = []
700 while stream.atEnd () == False:
701 commands.append (str (stream.readLine ()))
702 file.close ()
703 self._bridge._ipyShell.BatchCommands (commands)
704
706 """
707 Overview
708 ========
709 This is just a quick QMessageBox that pops up and shows the user the clickable urls for our
710 wiki-documentation sites.
711 """
712
713 dialog = QMessageBox (QMessageBox.NoIcon, "BASIN Wiki",
714 "<a href='http://www.physics.drexel.edu/basin_trac/kernel_trac'>Kernel Trac</a><br><br>" +
715 "<a href='http://www.physics.drexel.edu/basin_trac/remote_trac'>Remote Trac</a><br><br>" +
716 "<a href='http://www.physics.drexel.edu/basin_trac/client_trac'>Client Trac</a>")
717 dialog.setIconPixmap (QPixmap (Constants.ICON_DIR + "/help/wiki_large.png"))
718 dialog.setWindowIcon (QIcon (Constants.ICON_DIR + "/help/wiki.png"))
719 dialog.exec_ ()
720
721
723 """
724 Overview
725 ========
726 This is just a quick QMessageBox that pops up and shows the user a brief synopsis of Basin.
727 """
728
729 QMessageBox.information (self._bridge._mainWindow, "About BASIN",
730 "Beowulf PC clusters are now widely used in many branches of\n" +
731 "science where they have become key tools for the analysis of large\n" +
732 "datasets resulting from laboratory experiments, field observations\n" +
733 "or numerical simulations. However, although Beowulf clusters have\n" +
734 "been of great benefit to scientific research, no publicly available\n" +
735 "parallelized software package exist to perform even the most\n" +
736 "common operations needed in the analysis and visualization of\n" +
737 "large datasets. In sharp contrast with the situation for\n" +
738 "non-parallelized data analysis, where a wealth of software packages\n" +
739 "performing standard data-reduction tasks are available to\n" +
740 "researchers (e.g. IRAF, MIDAS), for parallel data analysis and\n" +
741 "visualization each individual group has tended to develop its own\n" +
742 "set of specialized tools. The increasing diffusion of multi-processor\n" +
743 "PCs further increase the demand of software packages for parallel\n" +
744 "data analysis.\n\n" +
745 "BASIN is a flexible, integrated suite of tools for parallel data\n" +
746 "analysis and visualization which has been designed and is currently\n" +
747 "been developed to address these concerns; BASIN is aimed at\n" +
748 "providing researchers with a package which allows them to harness\n" +
749 "the power of Beowulf PC clusters and multi-processor machines\n" +
750 "without necessarily being experts in parallel programming. While\n" +
751 "BASIN is motivated by problems particular to astrophysics, its core\n" +
752 "functionalities and parallel data distribution and manipulation are\n" +
753 "general end provide a number of general to easily develop libraries\n" +
754 "specific to data analysis in a number of different fields.")
755
757 """
758 Overview
759 ========
760 All of the functionality is handled within the ConnectionDialog, so that should be your primary
761 source of information.
762
763 Roughly speaking, it brings up a dialog which manages different profiles for connection to ipython
764 sessions. These profiles get saved to ~/.basin/client/connection.conf to be loaded later on.
765 """
766
767 dialog = Connection.ConnectionDialog (self._bridge)
768
770 """
771 Overview
772 ========
773 Disconnecting is quite easy, since all of the information about your connection is stored locally,
774 we can just destroy the rc variable in the ipython session. This will render you disconnected
775 without any harm.
776 """
777
778 self._bridge.makeLocal ()
779 self._bridge._ipyShell.SilentCommand ("del (rc)")
780 self._bridge.Disconnect ()
781
783 """
784 Overview
785 ========
786 This method will create an intance of the L{Preferences dialog<client.Preferences.Preferences>}.
787 The dialog will allow the user to change settings regarding:
788 - General/Miscellaneous
789 - Connection
790 - Toolbar
791 - Appearance
792 """
793
794 Preferences.Preferences (self._bridge)
795
796
799 QDialog.__init__ (self, bridge._mainWindow)
800
801 self._bridge = bridge
802 self._history = history
803
804 mainRect = self._bridge._mainWindow.geometry ()
805 width = mainRect.width ()
806 height = mainRect.height ()
807 x = mainRect.x () + int (width * 0.10)
808 y = mainRect.y () + int (height * 0.25)
809 width = int (width * 0.8)
810 height = int (height * 0.5)
811
812 dialog = QDialog ()
813 dialog.setGeometry (x, y, width, height)
814 dialog.setWindowIcon (QIcon (Constants.ICON_DIR + "/file/savebatch.png"))
815 dialog.setWindowTitle ("Save Script")
816 layout = QVBoxLayout (dialog)
817 dialog.setLayout (layout)
818 mainlayout = QHBoxLayout ()
819 layout.addLayout (mainlayout)
820
821 gbox = QGroupBox ("Users")
822 mainlayout.addWidget (gbox)
823 gboxlayout = QVBoxLayout ()
824 gbox.setLayout (gboxlayout)
825
826 vlayout = QVBoxLayout ()
827 mainlayout.addLayout (vlayout)
828 self._table = QTableWidget (len (self._history), 2, None)
829 self._table.setShowGrid (False)
830 QObject.connect (self._table, SIGNAL ("cellClicked (int,int)"), self.toggleCell)
831 vlayout.addWidget (self._table)
832 headers = QStringList (["Command", "User"])
833 self._table.setHorizontalHeaderLabels (headers)
834
835 total = len (self._history)
836 count = 0
837 self.users = []
838
839
840 _flip = False
841 for each in self._history:
842 at = each.find ("@")
843 userName = each[:at]
844 if userName[0] == "#":
845 userName = userName[1:]
846 _flip = True
847 if self.users.count (userName) == 0:
848 self.users.append (userName)
849 user = QTableWidgetItem (userName)
850 user.setFlags (Qt.ItemIsEnabled)
851 command = QTableWidgetItem (str (each[at + 1:]))
852 command.setFlags (Qt.ItemIsEditable | Qt.ItemIsEnabled)
853 if _flip == True:
854 color = QColor (80, 80, 80)
855 command.setBackgroundColor (color)
856 user.setBackgroundColor (color)
857 _flip = False
858 self._table.setItem (count, 0, command)
859 self._table.setItem (count, 1, user)
860 count += 1
861 self._table.resizeColumnsToContents ()
862
863 gboxlayout.addWidget (QLabel (QString (
864 "You may (de)select\n" +
865 "entire groups of\n" +
866 "commands to save to\n" +
867 "the batch based on\n" +
868 "the user who entered\n" +
869 "the command.")))
870 for each in self.users:
871 BatchCheck (each, self, gboxlayout)
872
873 buttonLayout = QHBoxLayout ()
874 vlayout.addLayout (buttonLayout)
875 saveButton = Constants.BQPushButton ("Save", buttonLayout)
876 QObject.connect (saveButton, SIGNAL ("clicked ()"), dialog.accept)
877 cancelButton = Constants.BQPushButton ("Cancel", buttonLayout)
878 QObject.connect (cancelButton, SIGNAL ("clicked ()"), dialog.reject)
879
880 layout.addWidget (QLabel (QString (
881 "Clicking on a row will either select it (turning it white), or deselect\n" + \
882 "it (turning it gray). Only those selected (white) commands will be saved\n" + \
883 "to a batch file.")))
884
885 self._rows = self._table.rowCount ()
886 dialog.exec_ ()
887
888 if dialog.result () == 1:
889 self.save ()
890
892 if self._table.item (row, col).backgroundColor () == QColor (255, 255, 255):
893 color = QColor (80, 80, 80)
894 self._table.item (row, 0).setBackgroundColor (color)
895 self._table.item (row, 1).setBackgroundColor (color)
896 else:
897 color = QColor (255, 255, 255)
898 self._table.item (row, 0).setBackgroundColor (color)
899 self._table.item (row, 1).setBackgroundColor (color)
900
902 color = QColor (255, 255, 255)
903 for index in xrange (self._table.rowCount ()):
904 if str (self._table.item (index, 1).text ()) == str (user):
905 self._table.item (index, 0).setBackgroundColor (color)
906 self._table.item (index, 1).setBackgroundColor (color)
907
909 color = QColor (80, 80, 80)
910 for index in xrange (self._table.rowCount ()):
911 if str (self._table.item (index, 1).text ()) == str (user):
912 self._table.item (index, 0).setBackgroundColor (color)
913 self._table.item (index, 1).setBackgroundColor (color)
914
916 commands = []
917 for index in xrange (self._table.rowCount ()):
918 if self._table.item (index, 0).backgroundColor () == QColor (255, 255, 255):
919 commands.append (str (self._table.item (index, 0).text ()))
920 return commands
921
923 self._bridge._ipyShell.ControllerCommand ("buffer_history.delete ()")
924 for index in xrange (self._table.rowCount ()):
925 if self._table.item (index, 0).backgroundColor () == QColor (255, 255, 255):
926 self._bridge._ipyShell.ControllerCommand ("buffer_history.append (\"" + \
927 str (self._table.item (index, 1).text ()) + "@" + \
928 str (self._table.item (index, 0).text ()).replace ("\"", "\\\\\"") + "\")")
929 else:
930 self._bridge._ipyShell.ControllerCommand ("buffer_history.append (\"#" + \
931 str (self._table.item (index, 1).text ()) + "@" + \
932 str (self._table.item (index, 0).text ()).replace ("\"", "\\\\\"") + "\")")
933
935 self.ReWriteBuffer ()
936 dialog = QFileDialog (None, QString ("Save Script"),
937 QString (str (QDir.home ().path ())),
938 QString ("BASIN Script (*.ipy)"))
939 dialog.setWindowIcon (QIcon (Constants.ICON_DIR + "/file/savebatch.png"))
940 dialog.setViewMode (QFileDialog.Detail)
941 dialog.setFileMode (QFileDialog.AnyFile)
942 dialog.setAcceptMode (QFileDialog.AcceptSave)
943 dialog.exec_ ()
944
945 files = dialog.selectedFiles ()
946 if not files.isEmpty ():
947 fileName = files[0]
948 if fileName[-4:] != ".ipy":
949 fileName = fileName + ".ipy"
950
951 file = QFile (fileName)
952 file.setPermissions (QFile.WriteOwner | QFile.ReadOwner | QFile.ReadUser | \
953 QFile.WriteUser | QFile.ReadGroup | QFile.WriteGroup | QFile.ReadOther)
954 file.open (QIODevice.WriteOnly)
955 commands = self.getSelectedCommands ()
956 for command in commands:
957 file.write (str (command) + "\n")
958 file.close ()
959
961 - def __init__ (self, label, parent, layout):
962 QCheckBox.__init__ (self, label)
963 QObject.connect (self, SIGNAL ("stateChanged (int)"), self.toggleSelection)
964 self._parent = parent
965 self._name = label
966 self.setCheckState (Qt.Checked)
967
968 layout.addWidget (self)
969
971 if val == 2:
972 self._parent.selectUser (self._name)
973 elif val == 0:
974 self._parent.deselectUser (self._name)
975
976
977
978
980 """
981 Overview
982 ========
983 Action reimplements QAction for the purpose of L{DockWidget<client.Dock.Widget>}s. Actions will automatically have their
984 triggers connected to their corresponding DockWidget
985 """
986
987 - def __init__ (self, icon, name, bridge, object = None):
988 self._bridge = bridge
989 QAction.__init__ (self, icon, name, None)
990 QObject.connect (self, SIGNAL ("triggered ()"), self.toggleEnabled)
991 QObject.connect (self, SIGNAL ("triggered ()"), self.ShowWidget)
992 self._widget = None
993 if object:
994 self._widget = object (bridge)
995
998
1012