Package client :: Module Actions
[hide private]
[frames] | no frames]

Source Code for Module client.Actions

   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   
22 -class Actions:
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
42 - def __init__ (self, bridge):
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 # When defining an action, actions which interact with the dock 70 # (ones whose actions become temporarily disabled), should be 71 # using the class Action, rather than QAction. An example of this 72 # would be any of the transformation functions. Actions, such as 73 # connect do not use the dock, and so should be initialized as a 74 # QAction. 75 76 77 #****************************************** 78 #File Actions 79 # 80 # define them here and they will propagate 81 # themselves throughout menus/toolbars 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 #General Functions Actions 127 # 128 # define them here and they will propagate 129 # themselves throughout menus/toolbars 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 #Plotting Actions 251 # 252 # define them here and they will propagate 253 # themselves throughout menus/toolbars 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 #Cosmology Actions 278 # 279 # define them here and they will propagate 280 # themselves throughout menus/toolbars 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 #Stellar Dynamics Actions 305 # 306 # define them here and they will propagate 307 # themselves throughout menus/toolbars 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 #Statistics Actions 350 # 351 # define them here and they will propagate 352 # themselves throughout menus/toolbars 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 #Transformations Actions 379 # 380 # define them here and they will propagate 381 # themselves throughout menus/toolbars 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 #Linear Algebra Actions 443 # 444 # define them here and they will propagate 445 # themselves throughout menus/toolbars 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 #Help Actions 472 # 473 # define them here and they will propagate 474 # themselves throughout menus/toolbars 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
486 - def menuConnect (self):
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
511 - def menuDisconnect (self):
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
539 - def menuRegionSelected (self):
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
552 - def menuRegionNotSelected (self):
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
564 - def importFile (self):
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 # Attempt a filename from the user, and if successful 582 # go ahead and open the file. 583 dialog = RemoteFile.RemoteFileBrowser (self._bridge) 584 for file in dialog.finalresult: 585 # Finds a valid name that isn't already in use 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 # execute the Region constructor in ipython 594 self._bridge.CursorBusy () 595 self._bridge._ipyShell.Command (str (var) + " = Region (\"" + str (file) + "\")") 596 self._bridge.CursorNorm ()
597 598
599 - def exportFile (self):
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
632 - def saveBatch (self):
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 # Make sure you aren't in the middle of a multi-line construct, and if you 654 # are then end it by sending a newline... 655 if len (self._bridge._ipyShell._commandLine._multiLineHistoryBuffer) > 0: 656 self._bridge._ipyShell.Command ("") 657 # Read in the server buffer history 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 # lop off the first 4 garbage lines from ipython 663 # Note that I haven't extensivley tested this with the preferences 664 # option that reduces output. 665 history = history.split ("\n")[4:] 666 if history == []: return 667 668 BatchSave (self._bridge, history)
669
670 - def loadBatch (self):
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
705 - def helpWiki (self):
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
722 - def helpAbout (self):
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
756 - def connect (self):
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
769 - def disconnect (self):
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
782 - def preferences (self):
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
797 -class BatchSave (QDialog):
798 - def __init__ (self, bridge, history):
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 # self._history is a list of strings of the format: 839 # user@command 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: # 'Save' 889 self.save ()
890
891 - def toggleCell (self, row, col):
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
901 - def selectUser (self, user):
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
908 - def deselectUser (self, user):
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
915 - def getSelectedCommands (self):
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
922 - def ReWriteBuffer (self):
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
934 - def save (self):
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
960 -class BatchCheck (QCheckBox):
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
970 - def toggleSelection (self, val):
971 if val == 2: 972 self._parent.selectUser (self._name) 973 elif val == 0: 974 self._parent.deselectUser (self._name)
975 976 977 978
979 -class Action (QAction):
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
996 - def toggleEnabled (self):
997 self._bridge._dock.DisableAction (self)
998
999 - def ShowWidget (self):
1000 if self._widget: 1001 if self._bridge._dock._current != self._widget: 1002 self._bridge._dock._current = self._widget 1003 self._widget.setVisible (True) 1004 try: 1005 self._widget.guessDefaults () 1006 except AttributeError: 1007 pass 1008 try: 1009 self._widget.DefaultCheck () 1010 except AttributeError: 1011 pass
1012