[4] | 1 | #!/usr/bin/env python |
---|
| 2 | |
---|
| 3 | ############################################################################ |
---|
| 4 | # |
---|
| 5 | # SAGE UI - A Graphical User Interface for SAGE |
---|
| 6 | # Copyright (C) 2005 Electronic Visualization Laboratory, |
---|
| 7 | # University of Illinois at Chicago |
---|
| 8 | # |
---|
| 9 | # All rights reserved. |
---|
| 10 | # |
---|
| 11 | # Redistribution and use in source and binary forms, with or without |
---|
| 12 | # modification, are permitted provided that the following conditions are met: |
---|
| 13 | # |
---|
| 14 | # * Redistributions of source code must retain the above copyright |
---|
| 15 | # notice, this list of conditions and the following disclaimer. |
---|
| 16 | # * Redistributions in binary form must reproduce the above |
---|
| 17 | # copyright notice, this list of conditions and the following disclaimer |
---|
| 18 | # in the documentation and/or other materials provided with the distribution. |
---|
| 19 | # * Neither the name of the University of Illinois at Chicago nor |
---|
| 20 | # the names of its contributors may be used to endorse or promote |
---|
| 21 | # products derived from this software without specific prior written permission. |
---|
| 22 | # |
---|
| 23 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
| 24 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
| 25 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
---|
| 26 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
---|
| 27 | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
| 28 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
---|
| 29 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
---|
| 30 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
---|
| 31 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
---|
| 32 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
---|
| 33 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
| 34 | # |
---|
| 35 | # Direct questions, comments etc about SAGE UI to www.evl.uic.edu/cavern/forum |
---|
| 36 | # |
---|
| 37 | # Author: Ratko Jagodic |
---|
| 38 | # Allan Spale |
---|
| 39 | # |
---|
| 40 | ############################################################################ |
---|
| 41 | |
---|
| 42 | |
---|
| 43 | |
---|
| 44 | |
---|
| 45 | ############################################################################ |
---|
| 46 | # |
---|
| 47 | # IMPORTS |
---|
| 48 | # |
---|
| 49 | ############################################################################ |
---|
| 50 | |
---|
| 51 | # python and wx stuff |
---|
| 52 | import string, sys, os, copy, optparse, time |
---|
| 53 | from threading import Timer |
---|
| 54 | import traceback as tb |
---|
| 55 | |
---|
| 56 | # hyperlink module is not (yet) included with wxPython as a standard module |
---|
| 57 | # so not all distributions have it |
---|
| 58 | global use_hyperlink |
---|
| 59 | use_hyperlink = True |
---|
| 60 | try: |
---|
| 61 | import wx.lib.hyperlink as hyperlink #for the about box |
---|
| 62 | except: |
---|
| 63 | use_hyperlink = False |
---|
| 64 | |
---|
| 65 | # if this UI should autosave |
---|
| 66 | global autosave |
---|
| 67 | |
---|
| 68 | # my stuff |
---|
| 69 | import Graph |
---|
| 70 | from sageGate import * |
---|
| 71 | from sageData import * |
---|
| 72 | from canvases import * |
---|
| 73 | from globals import * |
---|
| 74 | from users import * |
---|
| 75 | import preferences as prefs |
---|
| 76 | import launcherAdmin as lAdmin |
---|
| 77 | from sagePath import getUserPath |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | ############################################################################ |
---|
| 81 | # |
---|
| 82 | # GLOBAL CONSTANTS |
---|
| 83 | # |
---|
| 84 | ############################################################################ |
---|
| 85 | |
---|
| 86 | # current version of the UI |
---|
| 87 | VERSION = "3.0a" |
---|
| 88 | setUIVersion(VERSION) |
---|
| 89 | |
---|
| 90 | |
---|
| 91 | ### IDS used for the menu items: |
---|
| 92 | SAVE_STATE = 10 |
---|
| 93 | LOAD_STATE = 1 |
---|
| 94 | ASPECT_RATIO = 2 |
---|
| 95 | SAGE_COLOR = 3 |
---|
| 96 | PERF_DATA = 4 |
---|
| 97 | LOG_PERF_DATA = 5 |
---|
| 98 | RENDER_BW = 6 |
---|
| 99 | DISPLAY_BW = 7 |
---|
| 100 | RECORD_SESSION = 8 |
---|
| 101 | READ_SESSION = 9 |
---|
| 102 | SAGE_SHUTDOWN = 11 |
---|
| 103 | TILE_WINDOWS = 12 |
---|
| 104 | |
---|
| 105 | |
---|
| 106 | |
---|
| 107 | ############################################################################ |
---|
| 108 | |
---|
| 109 | class Log: |
---|
| 110 | def WriteText(self, text): |
---|
| 111 | if text[-1:] == '\n': |
---|
| 112 | text = text[:-1] |
---|
| 113 | wx.LogMessage(text) |
---|
| 114 | write = WriteText |
---|
| 115 | |
---|
| 116 | |
---|
| 117 | assertMode = wx.PYAPP_ASSERT_DIALOG |
---|
| 118 | |
---|
| 119 | |
---|
| 120 | |
---|
| 121 | ############################################################################ |
---|
| 122 | # |
---|
| 123 | # CLASS: DisplayNotebook |
---|
| 124 | # |
---|
| 125 | # DESCRIPTION: This is the main container (notebook) for the UI. It holds |
---|
| 126 | # one DisplayPage for every connection to SAGE. It also handles |
---|
| 127 | # page changes and menu changes when switching pages. |
---|
| 128 | # |
---|
| 129 | # DATE: June, 2005 |
---|
| 130 | # |
---|
| 131 | ############################################################################ |
---|
| 132 | |
---|
| 133 | class DisplayNotebook(wx.Notebook): |
---|
| 134 | |
---|
| 135 | def __init__(self, parent): |
---|
| 136 | wx.Notebook.__init__(self, parent, -1, style=wx.NO_BORDER) |
---|
| 137 | self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChange) |
---|
| 138 | |
---|
| 139 | # open the file for recording totals for all sites |
---|
| 140 | try: |
---|
| 141 | stDateTime = time.strftime("%Y%m%d-%H%M%S", time.localtime()) |
---|
| 142 | stFilename = "ALL_SITES_TOTALS-" + stDateTime |
---|
| 143 | stPath = opj(DATA_DIR, stFilename + ".txt") |
---|
| 144 | self._totalsFile = open(stPath, "w") |
---|
| 145 | self._totalsFile.write( time.asctime() + "\n" ) |
---|
| 146 | self._totalsFile.write( '-' * 40 + "\n" ) |
---|
| 147 | tempString = (' Timestamp(s) Disp BW(Gbps) Rend BW(Gbps) Num Sites\n') |
---|
| 148 | self._totalsFile.write(tempString) |
---|
| 149 | self._totalsFile.write( '-' * len(tempString) + "\n" ) |
---|
| 150 | self._totalsFile.flush() |
---|
| 151 | except: |
---|
| 152 | print "\n\nERROR: Unable to record performance totals in a file:\n" |
---|
| 153 | print "".join(tb.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])) |
---|
| 154 | self._totalsFile = None |
---|
| 155 | |
---|
| 156 | # start the timer to periodically record totals |
---|
| 157 | self.Bind(wx.EVT_TIMER, self.onPerfTimer) |
---|
| 158 | self.perfTimer = wx.Timer(self) |
---|
| 159 | self.perfTimer.Start(1000) |
---|
| 160 | |
---|
| 161 | |
---|
| 162 | ### this timer is called once per second to write the performance |
---|
| 163 | ### data totals to a file (for each sage connection) |
---|
| 164 | def onPerfTimer(self, event): |
---|
| 165 | totalR,totalD = 0,0 # totals for ALL sites... render and display |
---|
| 166 | recordTotals = False |
---|
| 167 | |
---|
| 168 | for pageIndex in range(0, self.GetPageCount()): |
---|
| 169 | p = self.GetPage(pageIndex) |
---|
| 170 | p.SaveSiteTotals() |
---|
| 171 | totalR += p.GetRenderTotal() |
---|
| 172 | totalD += p.GetDisplayTotal() |
---|
| 173 | |
---|
| 174 | # if no sites are logging data, dont record totals either |
---|
| 175 | if p.sageData.isLoggingEnabled(): |
---|
| 176 | recordTotals = True |
---|
| 177 | |
---|
| 178 | |
---|
| 179 | # now save the total of all sites |
---|
| 180 | if recordTotals and self._totalsFile: |
---|
| 181 | temp = "%12d %12.4f %12.4f %d\n" % (getTimeStamp(), |
---|
| 182 | totalD, |
---|
| 183 | totalR, |
---|
| 184 | self.GetPageCount()) |
---|
| 185 | self._totalsFile.write(temp) |
---|
| 186 | self._totalsFile.flush() |
---|
| 187 | |
---|
| 188 | |
---|
| 189 | ### test whether an application window was dropped on a notebook tab |
---|
| 190 | ### if it was, send a message to SAGE about the request |
---|
| 191 | ### used to request streaming of an application to multiple displays |
---|
| 192 | def DropTest(self, windowId, pt): |
---|
| 193 | tab_tuple = self.HitTest((pt[0], pt[1]*(-1))) # *(-1) since tabs are above the canvas (negative y coordinate with respect to it) |
---|
| 194 | newTab = tab_tuple[0] |
---|
| 195 | currentTab = self.GetSelection() |
---|
| 196 | |
---|
| 197 | if newTab == wx.NOT_FOUND or newTab == currentTab: |
---|
| 198 | return False |
---|
| 199 | else: |
---|
| 200 | currentPage = self.GetPage(currentTab) |
---|
| 201 | newPageMachine = self.GetPage(newTab).GetMachine() |
---|
| 202 | fsmIP = newPageMachine.GetSystemIP() |
---|
| 203 | fsmPort = newPageMachine.GetSystemPort() |
---|
| 204 | currentPage.sageGate.streamApp(windowId, fsmIP, fsmPort) #send a message |
---|
| 205 | self.SetSelection( newTab ) #open the new tab |
---|
| 206 | return True |
---|
| 207 | |
---|
| 208 | |
---|
| 209 | |
---|
| 210 | def GetFrame(self): |
---|
| 211 | return self.GetParent() |
---|
| 212 | |
---|
| 213 | |
---|
| 214 | ### this takes care of setting the proper menu items in the frame when a page changes |
---|
| 215 | ### it basically pulls the state of all the menu check items from the newly selected |
---|
| 216 | ### page and copies that hash into the hash of menu check items of the frame |
---|
| 217 | def OnPageChange(self, event): |
---|
| 218 | currentPageIndex = event.GetSelection() #must use event.GetSelection() instead of self.GetSelection() because WXMSW and WXMAC report the old selection otherwise |
---|
| 219 | if not currentPageIndex == -1: #windows reports -1 for some reason during creation |
---|
| 220 | newPage = self.GetPage(currentPageIndex) |
---|
| 221 | self.GetFrame().UpdateMenuItems(newPage.GetCurrentMenuItems()) #refresh the menu now so that it reflects the menu Items from the different page |
---|
| 222 | event.Skip() |
---|
| 223 | |
---|
| 224 | |
---|
| 225 | def SetDefaultMenuCheckItems(self, hashItems): |
---|
| 226 | self.defaultMenuCheckItems = hashItems.copy() |
---|
| 227 | |
---|
| 228 | |
---|
| 229 | def GetDefaultMenuCheckItems(self): |
---|
| 230 | return self.defaultMenuCheckItems.copy() |
---|
| 231 | |
---|
| 232 | |
---|
| 233 | def CloseCurrentPage(self, closeUI=True): |
---|
| 234 | if self.GetPageCount() < 2 and closeUI: |
---|
| 235 | self.GetFrame().Close(True) |
---|
| 236 | elif self.GetPageCount() > 1: |
---|
| 237 | currentPageIndex = self.GetSelection() |
---|
| 238 | if not currentPageIndex == -1: #windows reports -1 for some reason during creation |
---|
| 239 | page = self.GetPage(currentPageIndex) |
---|
| 240 | page.OnClose() |
---|
| 241 | self.DeletePage(currentPageIndex) |
---|
| 242 | |
---|
| 243 | #refresh the menu now so that it reflects the menu Items from the different page |
---|
| 244 | newPageIndex = self.GetSelection() |
---|
| 245 | newPage = self.GetPage(newPageIndex) |
---|
| 246 | self.GetFrame().UpdateMenuItems(newPage.GetCurrentMenuItems()) |
---|
| 247 | else: # this is the case if the user reconnected to SAGE when there was only one tab open previously |
---|
| 248 | currentPageIndex = self.GetSelection() |
---|
| 249 | if not currentPageIndex == -1: #windows reports -1 for some reason during creation |
---|
| 250 | page = self.GetPage(currentPageIndex) |
---|
| 251 | page.OnClose() |
---|
| 252 | self.DeletePage(currentPageIndex) |
---|
| 253 | |
---|
| 254 | |
---|
| 255 | def OnClose(self, event): |
---|
| 256 | for pageIndex in range(0, self.GetPageCount()): |
---|
| 257 | self.GetPage(pageIndex).OnClose(event) |
---|
| 258 | |
---|
| 259 | if self._totalsFile: self._totalsFile.close() |
---|
| 260 | self.perfTimer.Stop() |
---|
| 261 | |
---|
| 262 | |
---|
| 263 | def OnKeyEvent(self, event): |
---|
| 264 | if event.GetKeyCode() == wx.WXK_F9: |
---|
| 265 | currentPage = self.GetPage(self.GetSelection()) |
---|
| 266 | currentPage.GetDisplayCanvas().TileShapes() |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | def OnMenuEvent(self, event): |
---|
| 270 | eventId = event.GetId() |
---|
| 271 | menuItem = self.GetFrame().GetMenuBar().FindItemById(eventId) |
---|
| 272 | currentPage = self.GetPage(self.GetSelection()) |
---|
| 273 | |
---|
| 274 | # this ONLY changes the specific page's state of the selected menu item |
---|
| 275 | if menuItem.IsCheckable(): |
---|
| 276 | if menuItem.IsChecked(): |
---|
| 277 | currentPage.CheckMenuItem(eventId) |
---|
| 278 | else: |
---|
| 279 | currentPage.UncheckMenuItem(eventId) |
---|
| 280 | |
---|
| 281 | # call the correct menu event handler |
---|
| 282 | if eventId == SAVE_STATE: |
---|
| 283 | currentPage.OnSaveState() |
---|
| 284 | elif eventId == LOAD_STATE: |
---|
| 285 | currentPage.OnLoadState() |
---|
| 286 | elif eventId == ASPECT_RATIO: |
---|
| 287 | currentPage.OnMaintainAspectRatio(menuItem) |
---|
| 288 | elif eventId == SAGE_COLOR: |
---|
| 289 | currentPage.OnSAGEColorChange() |
---|
| 290 | elif eventId == PERF_DATA: |
---|
| 291 | currentPage.OnReceivePerfData(menuItem) |
---|
| 292 | elif eventId == LOG_PERF_DATA: |
---|
| 293 | currentPage.OnLogPerfData(menuItem) |
---|
| 294 | elif eventId == RENDER_BW: |
---|
| 295 | currentPage.OnShowRenderBW(menuItem) |
---|
| 296 | elif eventId == DISPLAY_BW: |
---|
| 297 | currentPage.OnShowDisplayBW(menuItem) |
---|
| 298 | elif eventId == RECORD_SESSION: |
---|
| 299 | currentPage.OnRecordSession(menuItem) |
---|
| 300 | elif eventId == READ_SESSION: |
---|
| 301 | currentPage.OnReadSession() |
---|
| 302 | elif eventId == SAGE_SHUTDOWN: |
---|
| 303 | currentPage.OnSAGEShutdown() |
---|
| 304 | else: |
---|
| 305 | pass #nothing... we dont know how to handle anything else |
---|
| 306 | |
---|
| 307 | |
---|
| 308 | |
---|
| 309 | |
---|
| 310 | |
---|
| 311 | ############################################################################ |
---|
| 312 | # |
---|
| 313 | # CLASS: DisplayPage |
---|
| 314 | # |
---|
| 315 | # DESCRIPTION: DisplayPage is a panel that holds all the controls associated |
---|
| 316 | # with one SAGE connection (DisplayCanvas and AppInfoPanel). There |
---|
| 317 | # is one for every connection and they are all placed in a notebook |
---|
| 318 | # (DisplayNotebook). |
---|
| 319 | # |
---|
| 320 | # DATE: June, 2005 |
---|
| 321 | # |
---|
| 322 | ############################################################################ |
---|
| 323 | |
---|
| 324 | class DisplayPage(wx.Panel): |
---|
| 325 | def __init__(self, parent, sageGate, usersClient, machineId, title): |
---|
| 326 | wx.Panel.__init__(self, parent, -1, style=wx.NO_BORDER) |
---|
| 327 | |
---|
| 328 | self.parent = parent |
---|
| 329 | # create main data storage and conectivity objects |
---|
| 330 | self.machineId = machineId |
---|
| 331 | self.usersClient = usersClient |
---|
| 332 | self.usersData = getUsersData() |
---|
| 333 | self.sageGate = sageGate |
---|
| 334 | self.sageData = SageData(sageGate, autosave, title.split('@')[1]) |
---|
| 335 | self.RegisterCallbacks() |
---|
| 336 | self.menuCheckItems = self.GetParent().GetDefaultMenuCheckItems() |
---|
| 337 | self.GetParent().GetFrame().UpdateMenuItems(self.GetCurrentMenuItems()) #update the menu items |
---|
| 338 | |
---|
| 339 | self.Bind(wx.EVT_SIZE, self.OnSize) |
---|
| 340 | |
---|
| 341 | # get the machine name |
---|
| 342 | self.siteName = machineId |
---|
| 343 | m = self.usersData.GetMachine(machineId) |
---|
| 344 | if m: |
---|
| 345 | self.siteName = m.GetName() |
---|
| 346 | |
---|
| 347 | # (AKS 2005-01-27) Performance graph object |
---|
| 348 | self.gmGraphManager = Graph.GraphManager( self, self.sageData ) |
---|
| 349 | # (AKS 2005-05-07) Create constants to identify totals graphs |
---|
| 350 | self.I_RENDER_BW_GRAPH = 1 |
---|
| 351 | self.I_DISPLAY_BW_GRAPH = 2 |
---|
| 352 | |
---|
| 353 | self.displayCanvas = DisplayCanvas(Log(), self, self.sageGate, self.sageData, self.gmGraphManager, title) |
---|
| 354 | self.appPanel = AppInfoPanel(self, self.sageGate, self, -1, (0,0), (self.displayCanvas.GetCanvasWidth(), 200), wx.NO_BORDER | wx.NO_FULL_REPAINT_ON_RESIZE) |
---|
| 355 | self.sageGate.getAppList() # this will get the list and fill the appPanel with it |
---|
| 356 | #self.Show() < -- this is done in DisplayCanvas.OnStatusMessage() (canvases.py) |
---|
| 357 | |
---|
| 358 | |
---|
| 359 | def GetFrame(self): |
---|
| 360 | return self.GetParent().GetParent() |
---|
| 361 | |
---|
| 362 | def GetNotebook(self): |
---|
| 363 | return self.GetParent() |
---|
| 364 | |
---|
| 365 | def GetNumPages(self): |
---|
| 366 | return self.GetNotebook().GetPageCount() |
---|
| 367 | |
---|
| 368 | def GetCurrentMenuItems(self): |
---|
| 369 | return self.menuCheckItems.copy() #return the current state of menu items specific to this display |
---|
| 370 | |
---|
| 371 | def CheckMenuItem(self, menuItemId): |
---|
| 372 | self.menuCheckItems[menuItemId] = True |
---|
| 373 | |
---|
| 374 | def UncheckMenuItem(self, menuItemId): |
---|
| 375 | self.menuCheckItems[menuItemId] = False |
---|
| 376 | |
---|
| 377 | def GetMachineId(self): |
---|
| 378 | return self.machineId |
---|
| 379 | |
---|
| 380 | def GetMachine(self): |
---|
| 381 | return self.usersData.GetMachine(self.machineId) |
---|
| 382 | |
---|
| 383 | |
---|
| 384 | #---------------------------------------------------------------------- |
---|
| 385 | |
---|
| 386 | def RegisterCallbacks(self): |
---|
| 387 | # (AKS 2005-01-13) |
---|
| 388 | # Register callbacks from SageData with SageGate |
---|
| 389 | # Whenever SageGate receives an update message from SAGE, |
---|
| 390 | # the client-side "app database" stored in SageData |
---|
| 391 | # will be updated and then issue its own callback function |
---|
| 392 | # to tell the registering app to retrieve and process |
---|
| 393 | # the updated data |
---|
| 394 | |
---|
| 395 | self.sageGate.registerCallbackFunction( 40000, self.sageData.setSageStatus ) |
---|
| 396 | self.sageGate.registerCallbackFunction( 40001, self.sageData.setSageAppInfo ) |
---|
| 397 | self.sageGate.registerCallbackFunction( 40002, self.sageData.setSagePerfInfo ) |
---|
| 398 | self.sageGate.registerCallbackFunction( 40003, self.sageData.sageAppShutDown ) |
---|
| 399 | self.sageGate.registerCallbackFunction( 40004, self.sageData.setDisplayInfo ) |
---|
| 400 | self.sageGate.registerCallbackFunction( 40005, self.sageData.setSageZValue ) |
---|
| 401 | self.sageGate.registerCallbackFunction( 40006, self.sageData.setSageAppExecConfig ) |
---|
| 402 | self.sageGate.registerCallbackFunction( 40007, self.sageData.setDisplayConnections ) |
---|
| 403 | |
---|
| 404 | return self.sageData |
---|
| 405 | |
---|
| 406 | |
---|
| 407 | #---------------------------------------------------------------------- |
---|
| 408 | |
---|
| 409 | |
---|
| 410 | def GetDisplayCanvas(self): |
---|
| 411 | return self.displayCanvas |
---|
| 412 | |
---|
| 413 | def GetAppInfoPanel(self): |
---|
| 414 | return self.appPanel |
---|
| 415 | |
---|
| 416 | def GetAppPanel(self): |
---|
| 417 | return self.appPanel.GetAppPanel() |
---|
| 418 | |
---|
| 419 | def GetInfoPanel(self): |
---|
| 420 | return self.appPanel.GetInfoPanel() |
---|
| 421 | |
---|
| 422 | def HideAppInfoPanel(self): |
---|
| 423 | self.oldHeight = self.GetClientSize().height |
---|
| 424 | newHeight = self.oldHeight - self.GetAppInfoPanel().GetSize().height + 60 |
---|
| 425 | self.GetFrame().SetClientSize( (self.GetFrame().GetClientSize().width, newHeight) ) |
---|
| 426 | self.GetAppInfoPanel().OnSize() |
---|
| 427 | |
---|
| 428 | def ShowAppInfoPanel(self): |
---|
| 429 | self.GetFrame().SetClientSize( (self.GetFrame().GetClientSize().width, self.oldHeight) ) |
---|
| 430 | self.GetAppInfoPanel().OnSize() |
---|
| 431 | |
---|
| 432 | |
---|
| 433 | def SaveSiteTotals(self): |
---|
| 434 | self.sageData.saveSiteTotals(self.siteName) |
---|
| 435 | |
---|
| 436 | def GetRenderTotal(self): |
---|
| 437 | """ returns total display bandwidth in gbps """ |
---|
| 438 | return self.sageData.getRenderBWTotal() |
---|
| 439 | |
---|
| 440 | def GetDisplayTotal(self): |
---|
| 441 | """ returns total rendering bandwidth in gbps """ |
---|
| 442 | return self.sageData.getDisplayBWTotal() |
---|
| 443 | |
---|
| 444 | |
---|
| 445 | #---------------------------------------------------------------------- |
---|
| 446 | # EVENT HANDLERS |
---|
| 447 | #---------------------------------------------------------------------- |
---|
| 448 | |
---|
| 449 | def OnDisplayInfo(self): |
---|
| 450 | pass |
---|
| 451 | |
---|
| 452 | |
---|
| 453 | def OnSize(self, event=None): |
---|
| 454 | self.SetSize(self.GetParent().GetClientSize())#event.GetSize()) |
---|
| 455 | if "__WXMSW__" in wx.PlatformInfo: #to bypass MS Windows' deferred resizing crap |
---|
| 456 | def doResize(): |
---|
| 457 | self.GetDisplayCanvas().OnSize(event) |
---|
| 458 | self.GetAppInfoPanel().OnSize(event) |
---|
| 459 | wx.CallAfter(doResize) |
---|
| 460 | else: |
---|
| 461 | self.GetDisplayCanvas().OnSize(event) |
---|
| 462 | self.GetAppInfoPanel().OnSize(event) |
---|
| 463 | |
---|
| 464 | |
---|
| 465 | def OnClose(self, evt=None): |
---|
| 466 | self.GetDisplayCanvas().Close() |
---|
| 467 | self.gmGraphManager.shutdown() # close all the graphs that might be open |
---|
| 468 | |
---|
| 469 | # close the "Totals" graphs (if open) |
---|
| 470 | #if self.menuCheckItems[RENDER_BW]: |
---|
| 471 | # self.removeGraph(self.I_RENDER_BW_GRAPH) |
---|
| 472 | #if self.menuCheckItems[DISPLAY_BW]: |
---|
| 473 | # self.removeGraph(self.I_DISPLAY_BW_GRAPH) |
---|
| 474 | |
---|
| 475 | # stop all the running features |
---|
| 476 | self.usersClient.Unregister(self.machineId) #tell the server that we are not registered in this room anymore |
---|
| 477 | self.sageData.stopLogging() |
---|
| 478 | #self.sageGate.StopRecording() |
---|
| 479 | self.sageGate.disconnectFromSage() #break the connection with SAGE |
---|
| 480 | |
---|
| 481 | |
---|
| 482 | # Menu -> Options -> Change SAGE Background Color |
---|
| 483 | def OnSAGEColorChange(self): |
---|
| 484 | (r,g,b) = self.sageData.getSAGEColor() |
---|
| 485 | colorData = wx.ColourData() |
---|
| 486 | colorData.SetColour(wx.Colour(r,g,b)) |
---|
| 487 | dlg = wx.ColourDialog(None, colorData) |
---|
| 488 | dlg.GetColourData().SetChooseFull(True) |
---|
| 489 | if dlg.ShowModal() == wx.ID_OK: |
---|
| 490 | data = dlg.GetColourData() |
---|
| 491 | self.sageData.setSAGEColor(data.GetColour().Get()) |
---|
| 492 | self.sageGate.setBgColor(self.sageData.getSAGEColor()) |
---|
| 493 | self.GetDisplayCanvas().ChangeBackgroundColor(self.sageData.getSAGEColor()) |
---|
| 494 | dlg.Destroy() |
---|
| 495 | |
---|
| 496 | |
---|
| 497 | # Menu -> File -> Shutdown SAGE |
---|
| 498 | def OnSAGEShutdown(self): |
---|
| 499 | dlg = wx.MessageDialog(self, "You are about to shutdown SAGE. All the currently connected "+ |
---|
| 500 | "users will be disconnected and all applications closed. \nAre "+ |
---|
| 501 | "you sure you want to continue?", "SAGE Shutdown", wx.YES_NO | wx.ICON_EXCLAMATION) |
---|
| 502 | if dlg.ShowModal() == wx.ID_YES: |
---|
| 503 | self.sageGate.shutdownSAGE() |
---|
| 504 | |
---|
| 505 | |
---|
| 506 | # Menu -> File -> Save State |
---|
| 507 | def OnSaveState(self): |
---|
| 508 | def OnStateSelected(evt): |
---|
| 509 | if nameText.GetValue() in stateHash: |
---|
| 510 | descriptionText.SetValue( stateHash[nameText.GetValue()] ) |
---|
| 511 | |
---|
| 512 | def OnDeleteState(evt): |
---|
| 513 | stateName = nameText.GetValue() |
---|
| 514 | if stateName in stateHash: |
---|
| 515 | if self.sageData.deleteState(stateName): |
---|
| 516 | descriptionText.Clear() |
---|
| 517 | nameText.Delete(nameText.FindString(stateName)) |
---|
| 518 | nameText.SetValue("") |
---|
| 519 | else: |
---|
| 520 | Message("Error deleting the saved state. Do you have the required permissions?", "Error Deleting") |
---|
| 521 | |
---|
| 522 | |
---|
| 523 | stateHash = self.sageData.getStateList() |
---|
| 524 | |
---|
| 525 | dlg = wx.Dialog(self, -1, "Save Display Session") |
---|
| 526 | okBtn = wx.Button(dlg, wx.ID_OK, "Save") |
---|
| 527 | delBtn = wx.Button(dlg, wx.ID_OK, " Delete ", style=wx.BU_EXACTFIT) |
---|
| 528 | delBtn.Bind(wx.EVT_BUTTON, OnDeleteState) |
---|
| 529 | |
---|
| 530 | states = stateHash.keys() |
---|
| 531 | states.sort() |
---|
| 532 | nameLabel = wx.StaticText(dlg, -1, "Session name:") |
---|
| 533 | nameText = wx.ComboBox(dlg, -1, "", choices=states, style=wx.CB_DROPDOWN) |
---|
| 534 | nameText.Bind(wx.EVT_COMBOBOX, OnStateSelected) |
---|
| 535 | nameText.SetFocus() |
---|
| 536 | descriptionLabel = wx.StaticText(dlg, -1, "Description:") |
---|
| 537 | descriptionText = wx.TextCtrl(dlg, -1, "", style=wx.TE_MULTILINE) |
---|
| 538 | |
---|
| 539 | nameSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
| 540 | nameSizer.Add(nameLabel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5) |
---|
| 541 | nameSizer.Add(nameText, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) |
---|
| 542 | nameSizer.Add(delBtn, 0, wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=5) |
---|
| 543 | |
---|
| 544 | sizer = wx.BoxSizer(wx.VERTICAL) |
---|
| 545 | sizer.Add(nameSizer, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.ALL, border=10) |
---|
| 546 | sizer.Add(descriptionLabel, 0, wx.ALIGN_LEFT | wx.LEFT | wx.RIGHT | wx.TOP, border=10) |
---|
| 547 | sizer.Add(descriptionText, 1, wx.EXPAND | wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, border=10) |
---|
| 548 | sizer.AddSpacer((15,15)) |
---|
| 549 | sizer.Add(okBtn, 0, wx.ALIGN_CENTER) |
---|
| 550 | sizer.AddSpacer((5,5)) |
---|
| 551 | |
---|
| 552 | dlg.SetSizer(sizer) |
---|
| 553 | dlg.SetSize((350, 300)) |
---|
| 554 | |
---|
| 555 | stateName = "" |
---|
| 556 | description = "" |
---|
| 557 | while dlg.ShowModal() == wx.ID_OK: |
---|
| 558 | stateName = nameText.GetValue() |
---|
| 559 | description = descriptionText.GetValue() |
---|
| 560 | if stateName == "": |
---|
| 561 | Message("Please name the session you are saving", "Session name required") |
---|
| 562 | continue |
---|
| 563 | elif stateName in stateHash: |
---|
| 564 | if wx.MessageBox("Session with that name already exists. Overwrite?", |
---|
| 565 | "Overwrite?", style=wx.YES_NO) == wx.YES: |
---|
| 566 | dlg.Destroy() |
---|
| 567 | else: |
---|
| 568 | continue |
---|
| 569 | self.sageData.saveState(stateName, description) |
---|
| 570 | break |
---|
| 571 | |
---|
| 572 | return |
---|
| 573 | |
---|
| 574 | |
---|
| 575 | |
---|
| 576 | # Menu -> File -> Load State |
---|
| 577 | def OnLoadState(self): |
---|
| 578 | def OnStateSelected(evt): |
---|
| 579 | descriptionText.SetLabel( stateHash[stateList.GetStringSelection()] ) |
---|
| 580 | |
---|
| 581 | def OnDeleteState(evt): |
---|
| 582 | stateName = stateList.GetStringSelection() |
---|
| 583 | if stateName in stateHash: |
---|
| 584 | if self.sageData.deleteState(stateName): |
---|
| 585 | stateList.Delete(stateList.FindString(stateName)) |
---|
| 586 | if not stateList.IsEmpty(): |
---|
| 587 | stateList.Select(0) |
---|
| 588 | descriptionText.SetLabel(stateHash[stateList.GetString(0)]) |
---|
| 589 | else: |
---|
| 590 | descriptionText.SetLabel("") |
---|
| 591 | else: |
---|
| 592 | Message("Error deleting the saved state. Do you have the required file permissions?", "Error Deleting") |
---|
| 593 | |
---|
| 594 | |
---|
| 595 | stateHash = self.sageData.getStateList() |
---|
| 596 | if len(stateHash) == 0: |
---|
| 597 | Message("No saved sessions exist", "") |
---|
| 598 | return |
---|
| 599 | |
---|
| 600 | dlg = wx.Dialog(self, -1, "Load Saved Session") |
---|
| 601 | okBtn = wx.Button(dlg, wx.ID_OK, "Load") |
---|
| 602 | okBtn.Disable() |
---|
| 603 | delBtn = wx.Button(dlg, wx.ID_OK, " Delete ", style=wx.BU_EXACTFIT) |
---|
| 604 | delBtn.Bind(wx.EVT_BUTTON, OnDeleteState) |
---|
| 605 | |
---|
| 606 | states = stateHash.keys() |
---|
| 607 | states.sort() |
---|
| 608 | states = stateHash.keys() |
---|
| 609 | states.sort() |
---|
| 610 | stateLabel = wx.StaticText(dlg, -1, "Saved Sessions:") |
---|
| 611 | stateList = wx.Choice(dlg, -1, choices=states) |
---|
| 612 | stateList.Bind(wx.EVT_CHOICE, OnStateSelected) |
---|
| 613 | descriptionBox = wx.StaticBox(dlg, -1, "Description:") |
---|
| 614 | descriptionText = wx.StaticText(dlg, -1, "", style=wx.ST_NO_AUTORESIZE) |
---|
| 615 | |
---|
| 616 | dbSizer = wx.StaticBoxSizer(descriptionBox, wx.VERTICAL) |
---|
| 617 | dbSizer.Add(descriptionText, 1, wx.EXPAND | wx.ALL, border=5) |
---|
| 618 | |
---|
| 619 | if len(stateHash) > 0: |
---|
| 620 | stateList.SetSelection(0) |
---|
| 621 | descriptionText.SetLabel( stateHash[stateList.GetString(0)] ) |
---|
| 622 | okBtn.Enable() |
---|
| 623 | |
---|
| 624 | stateSizer = wx.BoxSizer(wx.HORIZONTAL) |
---|
| 625 | stateSizer.Add(stateLabel, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT, border=5) |
---|
| 626 | stateSizer.Add(stateList, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL) |
---|
| 627 | stateSizer.Add(delBtn, 0, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.LEFT, border=5) |
---|
| 628 | |
---|
| 629 | sizer = wx.BoxSizer(wx.VERTICAL) |
---|
| 630 | sizer.Add(stateSizer, 0, wx.EXPAND | wx.ALIGN_LEFT | wx.ALL, border=10) |
---|
| 631 | sizer.Add(dbSizer, 1, wx.EXPAND | wx.ALIGN_LEFT | wx.RIGHT | wx.LEFT, border=10) |
---|
| 632 | sizer.AddSpacer((15,15)) |
---|
| 633 | sizer.Add(okBtn, 0, wx.ALIGN_CENTER) |
---|
| 634 | sizer.AddSpacer((5,5)) |
---|
| 635 | |
---|
| 636 | dlg.SetSizer(sizer) |
---|
| 637 | dlg.SetSize((350, 300)) |
---|
| 638 | |
---|
| 639 | if dlg.ShowModal() == wx.ID_OK: |
---|
| 640 | stateName = stateList.GetStringSelection() |
---|
| 641 | dlg.Destroy() |
---|
| 642 | if stateName == "": |
---|
| 643 | Message("No saved sessions exist", "") |
---|
| 644 | return |
---|
| 645 | self.sageData.loadState(stateName) |
---|
| 646 | |
---|
| 647 | return |
---|
| 648 | |
---|
| 649 | |
---|
| 650 | |
---|
| 651 | # Menu -> Options -> RecordSession |
---|
| 652 | def OnRecordSession(self, menuItem): |
---|
| 653 | if menuItem.IsChecked(): |
---|
| 654 | self.sageGate.StartRecording(menuItem) |
---|
| 655 | else: |
---|
| 656 | self.sageGate.StopRecording() |
---|
| 657 | |
---|
| 658 | |
---|
| 659 | # Menu -> Options -> ReadSession |
---|
| 660 | def OnReadSession(self): |
---|
| 661 | self.sageGate.PlaySession(self) |
---|
| 662 | |
---|
| 663 | |
---|
| 664 | # Menu -> Options -> MaintainAspectRatio |
---|
| 665 | def OnMaintainAspectRatio(self, menuItem): |
---|
| 666 | diagram = self.GetDisplayCanvas().GetDiagram() |
---|
| 667 | shapeList = diagram.GetShapeList() |
---|
| 668 | |
---|
| 669 | # store the flag for future apps |
---|
| 670 | self.GetDisplayCanvas().SetMaintainAspectRatio( menuItem.IsChecked() ) |
---|
| 671 | |
---|
| 672 | # change all the current apps' flags |
---|
| 673 | for s in shapeList: |
---|
| 674 | if ( s.__class__.__name__ == MyRectangleShape.__name__ ): |
---|
| 675 | s.SetMaintainAspectRatio( self.displayCanvas.GetMaintainAspectRatio() ) |
---|
| 676 | |
---|
| 677 | |
---|
| 678 | # Menu -> Performance -> Logging |
---|
| 679 | def OnLogPerfData(self, menuItem): |
---|
| 680 | self.sageData.setLoggingFlag( menuItem.IsChecked() ) |
---|
| 681 | |
---|
| 682 | |
---|
| 683 | # Menu -> Performance -> Receive Performance Data |
---|
| 684 | def OnReceivePerfData(self, menuItem): |
---|
| 685 | self.GetDisplayCanvas().ReceivePerformanceData( menuItem.IsChecked() ) |
---|
| 686 | |
---|
| 687 | |
---|
| 688 | # (AKS 2005-05-07) |
---|
| 689 | def OnShowRenderBW( self, menuItem ): |
---|
| 690 | if ( menuItem.IsChecked() == True ): |
---|
| 691 | self.__sgRenderBWGraph = Graph.SingleGraph( |
---|
| 692 | self, self.sageData.getRenderBandwidthGraph(), "Totals: Render Bandwidth", |
---|
| 693 | "Totals: Render Bandwidth", "Bandwidth (Mbps)", self.I_RENDER_BW_GRAPH ) |
---|
| 694 | self.__sgRenderBWGraph.registerShutdownCallback( self.removeGraph ) |
---|
| 695 | self.gmGraphManager.AddToUpdateList(self.__sgRenderBWGraph) |
---|
| 696 | else: |
---|
| 697 | self.gmGraphManager.RemoveFromUpdateList(self.__sgRenderBWGraph) |
---|
| 698 | self.__sgRenderBWGraph.manualShutdown() |
---|
| 699 | |
---|
| 700 | # end if |
---|
| 701 | |
---|
| 702 | |
---|
| 703 | # (AKS 2005-05-07) |
---|
| 704 | def OnShowDisplayBW( self, menuItem ): |
---|
| 705 | if ( menuItem.IsChecked() == True ): |
---|
| 706 | self.__sgDisplayBWGraph = Graph.SingleGraph( |
---|
| 707 | self, self.sageData.getDisplayBandwidthGraph(), "Totals: Display Bandwidth", |
---|
| 708 | "Totals: Display Bandwidth", "Bandwidth (Mbps)", self.I_DISPLAY_BW_GRAPH ) |
---|
| 709 | self.__sgDisplayBWGraph.registerShutdownCallback( self.removeGraph ) |
---|
| 710 | self.gmGraphManager.AddToUpdateList(self.__sgDisplayBWGraph) |
---|
| 711 | else: |
---|
| 712 | self.gmGraphManager.RemoveFromUpdateList(self.__sgDisplayBWGraph) |
---|
| 713 | self.__sgDisplayBWGraph.manualShutdown() |
---|
| 714 | |
---|
| 715 | # end if |
---|
| 716 | |
---|
| 717 | |
---|
| 718 | # (AKS 2005-05-07) |
---|
| 719 | def removeGraph( self, iGraphID ): |
---|
| 720 | if ( iGraphID == self.I_RENDER_BW_GRAPH ): |
---|
| 721 | self.gmGraphManager.RemoveFromUpdateList(self.__sgRenderBWGraph) |
---|
| 722 | self.__sgRenderBWGraph.manualShutdown() |
---|
| 723 | self.UncheckMenuItem(RENDER_BW) |
---|
| 724 | self.GetFrame().UpdateMenuItems(self.GetCurrentMenuItems()) #we must manually update the frame |
---|
| 725 | |
---|
| 726 | elif ( iGraphID == self.I_DISPLAY_BW_GRAPH ): |
---|
| 727 | self.gmGraphManager.RemoveFromUpdateList(self.__sgDisplayBWGraph) |
---|
| 728 | self.__sgDisplayBWGraph.manualShutdown() |
---|
| 729 | self.UncheckMenuItem(DISPLAY_BW) |
---|
| 730 | self.GetFrame().UpdateMenuItems(self.GetCurrentMenuItems()) #we must manually update the frame |
---|
| 731 | |
---|
| 732 | # end if; else, do nothing |
---|
| 733 | |
---|
| 734 | |
---|
| 735 | |
---|
| 736 | |
---|
| 737 | |
---|
| 738 | |
---|
| 739 | |
---|
| 740 | ############################################################################ |
---|
| 741 | # |
---|
| 742 | # CLASS: SAGEuiFrame |
---|
| 743 | # |
---|
| 744 | # DESCRIPTION: It describes the main frame that holds all the other controls. |
---|
| 745 | # It creates the two main canvases for the UI: |
---|
| 746 | # - the tiled display representation (upper canvas) |
---|
| 747 | # - the area for displaying app info (lower canvas) |
---|
| 748 | # |
---|
| 749 | # DATE: February 28, 2005 |
---|
| 750 | # |
---|
| 751 | ############################################################################ |
---|
| 752 | |
---|
| 753 | class SAGEuiFrame(wx.Frame): |
---|
| 754 | |
---|
| 755 | def __init__(self, sageGate, usersClient, firstMachineId, loadState, title=""): |
---|
| 756 | self.loadState = loadState # for automatically loading a saved display state upon startup |
---|
| 757 | |
---|
| 758 | if prefs.visual.GetFramePos() != None: |
---|
| 759 | position = prefs.visual.GetFramePos() |
---|
| 760 | else: |
---|
| 761 | position = (50,0) |
---|
| 762 | if "__WXMAC__" in wx.PlatformInfo: |
---|
| 763 | position = (50,50) |
---|
| 764 | |
---|
| 765 | wx.Frame.__init__(self, None, -1, "SAGE UI", |
---|
| 766 | pos=position, |
---|
| 767 | size=(500,300), |
---|
| 768 | style=wx.DEFAULT_FRAME_STYLE )#| wx.FULL_REPAINT_ON_RESIZE) |
---|
| 769 | |
---|
| 770 | # this is the only common thing between the pages |
---|
| 771 | self.usersClient = usersClient |
---|
| 772 | self.usersData = getUsersData() |
---|
| 773 | |
---|
| 774 | # so that we can kill SAGE from the UI |
---|
| 775 | self.sageGate = sageGate |
---|
| 776 | |
---|
| 777 | # make the menu |
---|
| 778 | self.SetMenuBar( self.CreateMenu() ) |
---|
| 779 | |
---|
| 780 | # bind any events we need |
---|
| 781 | self.Bind(wx.EVT_CLOSE, self.OnCloseFrame) |
---|
| 782 | self.Bind(wx.EVT_SIZE, self.OnSize) |
---|
| 783 | self.Bind(wx.EVT_MOVE, self.OnMove) |
---|
| 784 | self.Bind(wx.EVT_ACTIVATE, self.OnActivated) |
---|
| 785 | |
---|
| 786 | # This creates some pens and brushes that the OGL library uses. |
---|
| 787 | # It should be called after the app object has been created, but |
---|
| 788 | # before OGL is used. |
---|
| 789 | ogl.OGLInitialize() |
---|
| 790 | |
---|
| 791 | self.notebook = DisplayNotebook(self) |
---|
| 792 | tempHash = {} #extract the values of all the checkable menu items and send them to the notebook as default values |
---|
| 793 | for key, mi in self.menuCheckItems.iteritems(): |
---|
| 794 | tempHash[key] = mi.IsChecked() |
---|
| 795 | self.notebook.SetDefaultMenuCheckItems(tempHash) |
---|
| 796 | self.notebook.AddPage(DisplayPage(self.notebook, sageGate, usersClient, firstMachineId, title), title.split('@')[1], True) |
---|
| 797 | self.usersPanel = UsersPanel(self, usersClient) |
---|
| 798 | #self.Show() < -- this is done in DisplayCanvas.OnSAGEDisplaysConnection() (canvases.py) |
---|
| 799 | |
---|
| 800 | |
---|
| 801 | #---------------------------------------------------------------------- |
---|
| 802 | |
---|
| 803 | |
---|
| 804 | def CreateMenu(self): |
---|
| 805 | self.menuBar = wx.MenuBar() |
---|
| 806 | |
---|
| 807 | # File |
---|
| 808 | menuFile = wx.Menu() |
---|
| 809 | |
---|
| 810 | miFileNew = menuFile.Append(-1, "&New Connection\tCtrl-N", "Connect to another display") |
---|
| 811 | self.Bind(wx.EVT_MENU, self.OnNewConnection, miFileNew) |
---|
| 812 | |
---|
| 813 | miFileClose = menuFile.Append(-1, "Close Connection\tCtrl-W", "Close connection with this display") |
---|
| 814 | self.Bind(wx.EVT_MENU, self.OnCloseConnection, miFileClose) |
---|
| 815 | |
---|
| 816 | menuFile.AppendSeparator() |
---|
| 817 | |
---|
| 818 | miFileSave = menuFile.Append(SAVE_STATE, "&Save Session\tCtrl-S", "Save current session") |
---|
| 819 | self.Bind(wx.EVT_MENU, self.OnMenuItem, miFileSave) |
---|
| 820 | |
---|
| 821 | miFileLoad = menuFile.Append(LOAD_STATE, "&Load Session\tCtrl-O", "Load previously saved session") |
---|
| 822 | self.Bind(wx.EVT_MENU, self.OnMenuItem, miFileLoad) |
---|
| 823 | |
---|
| 824 | menuFile.AppendSeparator() |
---|
| 825 | |
---|
| 826 | miFileSAGEShutdown = menuFile.Append(SAGE_SHUTDOWN, "Shutdown SAGE", "Shutdown SAGE") |
---|
| 827 | self.Bind(wx.EVT_MENU, self.OnMenuItem, miFileSAGEShutdown) |
---|
| 828 | |
---|
| 829 | menuFile.AppendSeparator() |
---|
| 830 | |
---|
| 831 | miFileExit = menuFile.Append(-1, "E&xit\tAlt-X", "Exit demo") |
---|
| 832 | self.Bind(wx.EVT_MENU, self.OnExitButton, miFileExit) |
---|
| 833 | |
---|
| 834 | self.menuBar.Append(menuFile, "&File") |
---|
| 835 | |
---|
| 836 | |
---|
| 837 | # Options |
---|
| 838 | menuOptions = wx.Menu() |
---|
| 839 | |
---|
| 840 | self.miOptionsLibrary = menuOptions.Append(-1, "&File Library\tF2" , "Show File Library") |
---|
| 841 | self.Bind(wx.EVT_MENU, self.OnShowLibrary, self.miOptionsLibrary) |
---|
| 842 | |
---|
| 843 | self.miOptionsAspectRatio = menuOptions.Append(ASPECT_RATIO, "Preserve Aspect Ratio" , "Maintain Aspect Ratio?", wx.ITEM_CHECK) |
---|
| 844 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miOptionsAspectRatio) |
---|
| 845 | self.miOptionsAspectRatio.Check(prefs.visual.GetKeepAspectRatio()) |
---|
| 846 | |
---|
| 847 | self.miOptionsSAGEColor = menuOptions.Append(SAGE_COLOR, "Change SAGE Background Color" , "Change SAGE Background Color?") |
---|
| 848 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miOptionsSAGEColor) |
---|
| 849 | |
---|
| 850 | self.miOptionsShowChat = menuOptions.Append(-1, "Show Chat Window", "", wx.ITEM_CHECK) |
---|
| 851 | if self.usersClient.connected: |
---|
| 852 | if prefs.visual.IsChatShown() != None: |
---|
| 853 | self.miOptionsShowChat.Check(prefs.visual.IsChatShown()) |
---|
| 854 | self.Bind(wx.EVT_MENU, self.OnChatShow, self.miOptionsShowChat) |
---|
| 855 | |
---|
| 856 | self.miOptionsOutput = menuOptions.Append(-1, "Show Console Output", "", wx.ITEM_CHECK) |
---|
| 857 | self.Bind(wx.EVT_MENU, self.OnShowConsoleOutput, self.miOptionsOutput) |
---|
| 858 | self.miOptionsOutput.Check(False) |
---|
| 859 | |
---|
| 860 | self.miOptionsLauncherAdmin = menuOptions.Append(-1, "AppLauncher Admin" , "AppLauncher Admin Tool") |
---|
| 861 | self.Bind(wx.EVT_MENU, self.OnLauncherAdmin, self.miOptionsLauncherAdmin) |
---|
| 862 | |
---|
| 863 | self.menuBar.Append(menuOptions, "&Options") |
---|
| 864 | |
---|
| 865 | |
---|
| 866 | # Performance |
---|
| 867 | menuPerformance = wx.Menu() |
---|
| 868 | |
---|
| 869 | self.miPerformancePerformance = menuPerformance.Append(PERF_DATA, "Receive Performance Data", "", wx.ITEM_CHECK) |
---|
| 870 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miPerformancePerformance) |
---|
| 871 | self.miPerformancePerformance.Check(prefs.visual.GetReceivePerformanceData()) |
---|
| 872 | |
---|
| 873 | self.miPerformanceLogging = menuPerformance.Append(LOG_PERF_DATA, "Log Performance Data" , "Permit performance data logging to a file.", wx.ITEM_CHECK) |
---|
| 874 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miPerformanceLogging) |
---|
| 875 | self.miPerformanceLogging.Check(True) |
---|
| 876 | |
---|
| 877 | self.miPerformanceRenderBWGraph = menuPerformance.Append(RENDER_BW, "Show Total Rendering Bandwidth" , "Show the graph for Total Rendering Bandwidth.", wx.ITEM_CHECK) |
---|
| 878 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miPerformanceRenderBWGraph) |
---|
| 879 | self.miPerformanceRenderBWGraph.Check(False) |
---|
| 880 | |
---|
| 881 | self.miPerformanceDisplayBWGraph = menuPerformance.Append(DISPLAY_BW, "Show Total Display Bandwidth" , "Show the graph for Total Display Bandwidth.", wx.ITEM_CHECK) |
---|
| 882 | self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miPerformanceDisplayBWGraph) |
---|
| 883 | self.miPerformanceDisplayBWGraph.Check(False) |
---|
| 884 | |
---|
| 885 | self.menuBar.Append(menuPerformance, "&Performance") |
---|
| 886 | |
---|
| 887 | |
---|
| 888 | # Session |
---|
| 889 | ## menuSession = wx.Menu() |
---|
| 890 | ## self.miSessionRecord = menuSession.Append(RECORD_SESSION, "Record Session" , "", wx.ITEM_CHECK) |
---|
| 891 | ## self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miSessionRecord) |
---|
| 892 | ## self.miSessionRead = menuSession.Append(READ_SESSION, "Read Session" , "") |
---|
| 893 | ## self.Bind(wx.EVT_MENU, self.OnMenuItem, self.miSessionRead) |
---|
| 894 | ## self.menuBar.Append(menuSession, "&Session") |
---|
| 895 | |
---|
| 896 | |
---|
| 897 | # Help |
---|
| 898 | menuHelp = wx.Menu() |
---|
| 899 | self.miAbout = menuHelp.Append(-1, "About SAGE UI\tF1", "") |
---|
| 900 | self.Bind(wx.EVT_MENU, self.OnAbout, self.miAbout) |
---|
| 901 | self.menuBar.Append(menuHelp, "&Help") |
---|
| 902 | |
---|
| 903 | |
---|
| 904 | # store all the menu check items that are display dependent |
---|
| 905 | self.menuCheckItems = {} |
---|
| 906 | self.menuCheckItems[ASPECT_RATIO] = self.miOptionsAspectRatio#.IsChecked() |
---|
| 907 | self.menuCheckItems[PERF_DATA] = self.miPerformancePerformance#.IsChecked() |
---|
| 908 | self.menuCheckItems[LOG_PERF_DATA] = self.miPerformanceLogging#.IsChecked() |
---|
| 909 | self.menuCheckItems[RENDER_BW] = self.miPerformanceRenderBWGraph#.IsChecked() |
---|
| 910 | self.menuCheckItems[DISPLAY_BW] = self.miPerformanceDisplayBWGraph#.IsChecked() |
---|
| 911 | #self.menuCheckItems[RECORD_SESSION] = self.miSessionRecord#.IsChecked() |
---|
| 912 | |
---|
| 913 | |
---|
| 914 | # bind keystrokes to the frame |
---|
| 915 | self.Bind(wx.EVT_KEY_DOWN, self.OnKeyEvent) |
---|
| 916 | |
---|
| 917 | return self.menuBar |
---|
| 918 | |
---|
| 919 | |
---|
| 920 | #---------------------------------------------------------------------- |
---|
| 921 | |
---|
| 922 | def UpdateMenuItems(self, newMenuItems): |
---|
| 923 | # update the menu with the specific menu items from the current page |
---|
| 924 | for k,mi in self.menuCheckItems.iteritems(): |
---|
| 925 | mi.Check(newMenuItems[k]) |
---|
| 926 | self.menuBar.Refresh() |
---|
| 927 | |
---|
| 928 | |
---|
| 929 | def GetUsersPanel(self): |
---|
| 930 | return self.usersPanel |
---|
| 931 | |
---|
| 932 | |
---|
| 933 | |
---|
| 934 | ## def Reconnect(self): |
---|
| 935 | ## dlg = wx.MessageDialog(None, "Connection to SAGE has closed.\nYou will have to reconnect when SAGE becomes available again.", "SAGE Connection Closed", style=wx.OK) |
---|
| 936 | ## #btn = wx.Button(dlg, 999, "Reconnect") |
---|
| 937 | ## if dlg.ShowModal() == wx.ID_OK: |
---|
| 938 | ## self.notebook.CloseCurrentPage(closeUI=False) |
---|
| 939 | ## sageGate = SageGate() |
---|
| 940 | ## cd = ConnectionDialog(sageGate, self.usersClient, firstConnection=False) |
---|
| 941 | ## title = self.usersData.GetMyUsername() + " @ " + cd.hostname |
---|
| 942 | ## self.notebook.AddPage(DisplayPage(self.notebook, sageGate, self.usersData, self.usersClient, cd.host, title), title, True) |
---|
| 943 | |
---|
| 944 | ## dlg.Destroy() |
---|
| 945 | |
---|
| 946 | #---------------------------------------------------------------------- |
---|
| 947 | # EVENT HANDLERS |
---|
| 948 | #---------------------------------------------------------------------- |
---|
| 949 | |
---|
| 950 | |
---|
| 951 | def OnActivated(self, evt): |
---|
| 952 | """ happens only when the frame is shown because we unbind the event below """ |
---|
| 953 | self.Disconnect(-1,-1,wx.wxEVT_ACTIVATE) |
---|
| 954 | |
---|
| 955 | # load the saved state of the display if requested |
---|
| 956 | if self.loadState: |
---|
| 957 | sageData = self.notebook.GetPage(self.notebook.GetSelection()).sageData |
---|
| 958 | t = Timer(4, sageData.loadState, [self.loadState]) |
---|
| 959 | t.start() |
---|
| 960 | |
---|
| 961 | |
---|
| 962 | def OnSize(self, event=None): |
---|
| 963 | if "__WXMSW__" in wx.PlatformInfo: #to bypass windows' deferred resizing crap |
---|
| 964 | def doResize(): |
---|
| 965 | #self.notebook.OnSize(event) |
---|
| 966 | if self.usersClient.connected: |
---|
| 967 | self.usersPanel.OnFrameMove() |
---|
| 968 | wx.CallAfter(doResize) |
---|
| 969 | else: |
---|
| 970 | #self.notebook.OnSize(event) |
---|
| 971 | if self.usersClient.connected: |
---|
| 972 | self.usersPanel.OnFrameMove() |
---|
| 973 | event.Skip() #resize the notebook |
---|
| 974 | |
---|
| 975 | |
---|
| 976 | def OnMove(self, event): |
---|
| 977 | if self.usersClient.connected: |
---|
| 978 | self.usersPanel.OnFrameMove() |
---|
| 979 | |
---|
| 980 | |
---|
| 981 | def OnKeyEvent(self, event): |
---|
| 982 | #self.notebook.OnKeyEvent(event) |
---|
| 983 | event.Skip() |
---|
| 984 | |
---|
| 985 | |
---|
| 986 | def OnCloseFrame(self, evt): |
---|
| 987 | # save the visual preferences (frame size, position, chat panel) |
---|
| 988 | prefs.visual.SetAll(self.GetClientSize(), self.GetPosition(), self.usersPanel.IsShown()) |
---|
| 989 | |
---|
| 990 | # close all connections to SAGEs |
---|
| 991 | self.notebook.OnClose(evt) |
---|
| 992 | |
---|
| 993 | #if self.usersClient.connected: |
---|
| 994 | self.usersPanel.Disconnect() |
---|
| 995 | |
---|
| 996 | |
---|
| 997 | # (AKS 2005-05-06) Delete all temp files of size 0 created when ignoring logging function |
---|
| 998 | # Instead of allowing for the possibility that new apps start and their respective log |
---|
| 999 | # files are not made causing an error, allow the new app's file to be created but do |
---|
| 1000 | # not write to it. Later, delete the 0-size file. |
---|
| 1001 | try: #in case the file and directory permissions are not right |
---|
| 1002 | listFilenames = os.listdir( DATA_DIR ) |
---|
| 1003 | |
---|
| 1004 | # remove files that were never written or minimally written (i.e. <= 1K) |
---|
| 1005 | for stFilename in listFilenames: |
---|
| 1006 | stFilename = opj(DATA_DIR, stFilename) |
---|
| 1007 | stCompleteFilename = os.path.normcase( stFilename ) |
---|
| 1008 | structStats = os.stat( stCompleteFilename ) |
---|
| 1009 | |
---|
| 1010 | if ( structStats.st_size <= 1024 ): |
---|
| 1011 | os.remove( stCompleteFilename ) |
---|
| 1012 | print "Deleting", stCompleteFilename |
---|
| 1013 | # end if |
---|
| 1014 | # end loop |
---|
| 1015 | except: |
---|
| 1016 | pass |
---|
| 1017 | |
---|
| 1018 | self.DestroyChildren() |
---|
| 1019 | self.Destroy() |
---|
| 1020 | wx.GetApp().ExitMainLoop() |
---|
| 1021 | |
---|
| 1022 | |
---|
| 1023 | #---------------------------------------------------------------------- |
---|
| 1024 | # MENU HANDLERS |
---|
| 1025 | #---------------------------------------------------------------------- |
---|
| 1026 | |
---|
| 1027 | |
---|
| 1028 | ### this catches all the menu events that are display specific |
---|
| 1029 | def OnMenuItem(self, event): |
---|
| 1030 | self.notebook.OnMenuEvent(event) |
---|
| 1031 | |
---|
| 1032 | # Menu -> File -> Exit |
---|
| 1033 | def OnExitButton(self, evt): |
---|
| 1034 | self.Close(True) |
---|
| 1035 | |
---|
| 1036 | # Menu -> Help -> About |
---|
| 1037 | def OnAbout(self, evt): |
---|
| 1038 | AboutDialog(self) |
---|
| 1039 | |
---|
| 1040 | # Menu -> Chat -> Show |
---|
| 1041 | def OnChatShow(self, evt): |
---|
| 1042 | if self.miOptionsShowChat.IsChecked(): |
---|
| 1043 | self.usersPanel.Show() |
---|
| 1044 | else: |
---|
| 1045 | self.usersPanel.Hide() |
---|
| 1046 | |
---|
| 1047 | # Menu -> Options -> AppLauncher Admin |
---|
| 1048 | def OnLauncherAdmin(self, evt): |
---|
| 1049 | lAdmin.MainFrame(getSAGEServer()) |
---|
| 1050 | |
---|
| 1051 | # Menu -> Options -> Show File Library |
---|
| 1052 | def OnShowLibrary(self, evt): |
---|
| 1053 | self.notebook.GetPage(self.notebook.GetSelection()).displayCanvas.ShowLibrary() |
---|
| 1054 | |
---|
| 1055 | # Menu -> Options -> Show Console Output |
---|
| 1056 | def OnShowConsoleOutput(self, evt): |
---|
| 1057 | if self.miOptionsOutput.IsChecked(): |
---|
| 1058 | wx.GetApp().RestoreStdio() |
---|
| 1059 | else: |
---|
| 1060 | try: |
---|
| 1061 | wx.GetApp().RedirectStdio( LOG_FILE ) |
---|
| 1062 | except IOError: |
---|
| 1063 | message = "\nCould not redirect output to a log file. Probably because of file permissions." |
---|
| 1064 | message = message+"\nInstead, output will be printed in the console" |
---|
| 1065 | dlg = wx.MessageDialog(self, message, "Error redirecting output", style=wx.OK) |
---|
| 1066 | dlg.ShowModal() |
---|
| 1067 | dlg.Destroy() |
---|
| 1068 | wx.GetApp().RestoreStdio() |
---|
| 1069 | self.miOptionsOutput.Check(True) |
---|
| 1070 | |
---|
| 1071 | # Menu -> File -> New |
---|
| 1072 | def OnNewConnection(self, event): |
---|
| 1073 | sageGate = SageGate() |
---|
| 1074 | |
---|
| 1075 | # initialize the dialog and show it. If it returns False, the user pressed quit |
---|
| 1076 | # otherwise the connection to SAGE was successful and the username was accepted |
---|
| 1077 | # so create the tab, show it and continue with execution |
---|
| 1078 | cd = ConnectionDialog(sageGate, self.usersClient, firstConnection=False) |
---|
| 1079 | if cd.ShowDialog(): |
---|
| 1080 | title = self.usersData.GetMyUsername() + " @ " + cd.GetMachine().GetName() |
---|
| 1081 | self.notebook.AddPage(DisplayPage(self.notebook, sageGate, self.usersClient, cd.GetMachine().GetId(), title), cd.GetMachine().GetName(), True) |
---|
| 1082 | |
---|
| 1083 | return True |
---|
| 1084 | |
---|
| 1085 | # Menu -> File -> Close |
---|
| 1086 | def OnCloseConnection(self, event): |
---|
| 1087 | self.notebook.CloseCurrentPage() |
---|
| 1088 | |
---|
| 1089 | |
---|
| 1090 | ############################################################################ |
---|
| 1091 | # |
---|
| 1092 | # CLASS: AboutDialog |
---|
| 1093 | # |
---|
| 1094 | # DESCRIPTION: It just displays the about box. |
---|
| 1095 | # |
---|
| 1096 | # DATE: June 2005 |
---|
| 1097 | # |
---|
| 1098 | ############################################################################ |
---|
| 1099 | |
---|
| 1100 | class AboutDialog(wx.Dialog): |
---|
| 1101 | def __init__(self, parent): |
---|
| 1102 | titleText = "SAGE Graphical User Interface" |
---|
| 1103 | contentText = "version " + str(VERSION) + "\n\n\n" + "For more information go to:" |
---|
| 1104 | linkUrl = "www.evl.uic.edu/cavern/sage" |
---|
| 1105 | link2Text = "Direct questions or comments to:" |
---|
| 1106 | link2Url = "www.evl.uic.edu/cavern/forum" |
---|
| 1107 | |
---|
| 1108 | wx.Dialog.__init__(self, parent, -1, "About SAGE UI", style=wx.CLOSE_BOX) |
---|
| 1109 | okBtn = wx.Button(self, wx.ID_OK, "OK") |
---|
| 1110 | title = wx.StaticText(self, -1, titleText, style=wx.ALIGN_CENTER) |
---|
| 1111 | title.SetFont(BoldFont(title)) |
---|
| 1112 | |
---|
| 1113 | if use_hyperlink: |
---|
| 1114 | link = hyperlink.HyperLinkCtrl(self, wx.ID_ANY, linkUrl, URL="http://"+linkUrl) |
---|
| 1115 | link.AutoBrowse(True) |
---|
| 1116 | link2 = hyperlink.HyperLinkCtrl(self, wx.ID_ANY, link2Url, URL="http://"+link2Url) |
---|
| 1117 | link2.AutoBrowse(True) |
---|
| 1118 | else: |
---|
| 1119 | link = wx.StaticText(self, -1, linkUrl, style=wx.ALIGN_CENTER) |
---|
| 1120 | link2 = wx.StaticText(self, -1, link2Url, style=wx.ALIGN_CENTER) |
---|
| 1121 | |
---|
| 1122 | text = wx.StaticText(self, -1, contentText, style=wx.ALIGN_CENTER) |
---|
| 1123 | text2 = wx.StaticText(self, -1, link2Text, style=wx.ALIGN_CENTER) |
---|
| 1124 | |
---|
| 1125 | |
---|
| 1126 | sizer = wx.BoxSizer(wx.VERTICAL) |
---|
| 1127 | sizer.AddSpacer((20, 20)) |
---|
| 1128 | sizer.Add(title, 0, wx.ALIGN_CENTER | wx.RIGHT | wx.LEFT, border=15) |
---|
| 1129 | sizer.Add(text, 0, wx.ALIGN_CENTER) |
---|
| 1130 | sizer.Add(link, 0, wx.ALIGN_CENTER) |
---|
| 1131 | sizer.AddSpacer((15,15)) |
---|
| 1132 | sizer.Add(text2, 0, wx.ALIGN_CENTER) |
---|
| 1133 | sizer.Add(link2, 0, wx.ALIGN_CENTER) |
---|
| 1134 | sizer.AddSpacer((15,15)) |
---|
| 1135 | sizer.Add(okBtn, 0, wx.ALIGN_CENTER) |
---|
| 1136 | sizer.AddSpacer((5,5)) |
---|
| 1137 | self.SetSizer(sizer) |
---|
| 1138 | self.Fit() |
---|
| 1139 | self.ShowModal() |
---|
| 1140 | self.Destroy() |
---|
| 1141 | |
---|
| 1142 | |
---|
| 1143 | |
---|
| 1144 | |
---|
| 1145 | |
---|
| 1146 | ############################################################################ |
---|
| 1147 | # |
---|
| 1148 | # CLASS: SAGEui |
---|
| 1149 | # |
---|
| 1150 | # DESCRIPTION: This is a starting point for wx. It extends wx.App and |
---|
| 1151 | # creates the SAGEuiFrame to place the canvases in. It also displays |
---|
| 1152 | # the initial dialogs for the User profile and SAGE connection. |
---|
| 1153 | # |
---|
| 1154 | # DATE: October 2004 |
---|
| 1155 | # |
---|
| 1156 | ############################################################################ |
---|
| 1157 | |
---|
| 1158 | class SAGEui(wx.App): |
---|
| 1159 | def __init__(self, usersServerIP, usersServerPort, verbose, autologinMachine, loadState): |
---|
| 1160 | self.usersServerIP = usersServerIP |
---|
| 1161 | self.usersServerPort = usersServerPort |
---|
| 1162 | self.autologinMachine = autologinMachine |
---|
| 1163 | self.loadState = loadState |
---|
| 1164 | |
---|
| 1165 | if verbose: |
---|
| 1166 | wx.App.__init__(self, redirect=False) |
---|
| 1167 | else: |
---|
| 1168 | try: |
---|
| 1169 | wx.App.__init__(self, redirect=True, filename=LOG_FILE) |
---|
| 1170 | except IOError: |
---|
| 1171 | print "\nError: Could not redirect output to a log file. Possibly because of file permissions." |
---|
| 1172 | print "Instead, output will be printed in the console" |
---|
| 1173 | wx.App.__init__(self, redirect=False) |
---|
| 1174 | |
---|
| 1175 | def Skip( self, evt ): |
---|
| 1176 | pass |
---|
| 1177 | |
---|
| 1178 | def OnInit(self): |
---|
| 1179 | wx.Log_SetActiveTarget(wx.LogStderr()) |
---|
| 1180 | self.SetAssertMode(assertMode) |
---|
| 1181 | socket.setdefaulttimeout(2) |
---|
| 1182 | |
---|
| 1183 | # initialize network communication with: |
---|
| 1184 | # sageGate... the connection to SAGE |
---|
| 1185 | # usersClient...the connection to UsersServer |
---|
| 1186 | # usersData... the datastructure used in conjunction with usersClient |
---|
| 1187 | usersData = UsersDatastructure() |
---|
| 1188 | setUsersData(usersData) #store it in a global scope |
---|
| 1189 | sageGate = SageGate() |
---|
| 1190 | usersClient = UsersClient() |
---|
| 1191 | |
---|
| 1192 | # initialize the dialog and show it. If it returns False, the user pressed quit |
---|
| 1193 | # otherwise the connection to SAGE was successful and the username was accepted |
---|
| 1194 | # so show the frame and continue with execution |
---|
| 1195 | cd = ConnectionDialog(sageGate, usersClient, self.usersServerIP, usersServerPort = self.usersServerPort, autologinMachine=self.autologinMachine) |
---|
| 1196 | if cd.ShowDialog(): |
---|
| 1197 | title = usersData.GetMyUsername() + " @ " + cd.GetMachine().GetName() |
---|
| 1198 | self.frame = SAGEuiFrame(sageGate, usersClient, cd.GetMachine().GetId(), self.loadState, title) |
---|
| 1199 | self.SetTopWindow(self.frame) |
---|
| 1200 | else: |
---|
| 1201 | usersClient.Disconnect() |
---|
| 1202 | sys.exit(0) |
---|
| 1203 | |
---|
| 1204 | return True |
---|
| 1205 | |
---|
| 1206 | |
---|
| 1207 | |
---|
| 1208 | |
---|
| 1209 | ############################################################################ |
---|
| 1210 | # |
---|
| 1211 | # Main entry point for the application |
---|
| 1212 | # |
---|
| 1213 | ############################################################################ |
---|
| 1214 | |
---|
| 1215 | ### sets up the parser for the command line options |
---|
| 1216 | def get_commandline_options(): |
---|
| 1217 | parser = optparse.OptionParser() |
---|
| 1218 | |
---|
| 1219 | h = "if set, prints output to console, otherwise to ~/.sageConfig/sageui/output_log.txt" |
---|
| 1220 | parser.add_option("-v", "--verbose", action="store_true", help=h, dest="verbose", default=False) |
---|
| 1221 | |
---|
| 1222 | h = "which sage server / connection manager to use (default is sage.sl.startap.net)" |
---|
| 1223 | parser.add_option("-s", "--server", dest="server", help=h, default="sage.sl.startap.net") |
---|
| 1224 | |
---|
| 1225 | h = "change the port number of the sage server (default is 15558)" |
---|
| 1226 | parser.add_option("-p", "--port", help=h, type="int", dest="port", default=15558) |
---|
| 1227 | |
---|
| 1228 | h = "override which application launcher to use (by default it looks for one on the same machine as sage master. Specify as machine:port)" |
---|
| 1229 | parser.add_option("-l", "--launcher", dest="launcher", help=h, default="") |
---|
| 1230 | |
---|
| 1231 | h = "try autologin to this sage name (what fsManager reports to connection manager from fsManager.conf )" |
---|
| 1232 | parser.add_option("-a", "--autologin", dest="autologin", help=h, default=None) |
---|
| 1233 | |
---|
| 1234 | h = "upon startup load this saved state (write saved state name from saved-states directory)" |
---|
| 1235 | parser.add_option("-o", "--load_state", dest="load_state", help=h, default=None) |
---|
| 1236 | |
---|
| 1237 | h = "perform autosave?" |
---|
| 1238 | parser.add_option("-t", "--autosave", action="store_true", help=h, dest="autosave", default=False) |
---|
| 1239 | |
---|
| 1240 | return parser.parse_args() |
---|
| 1241 | |
---|
| 1242 | |
---|
| 1243 | |
---|
| 1244 | def main(argv): |
---|
| 1245 | os.chdir(sys.path[0]) # change to the folder where script is running |
---|
| 1246 | global autosave |
---|
| 1247 | verbose = False |
---|
| 1248 | usersServerIP = "74.114.99.36" |
---|
| 1249 | usersServerPort = 15558 |
---|
| 1250 | |
---|
| 1251 | # parse the command line params |
---|
| 1252 | (options, args) = get_commandline_options() |
---|
| 1253 | verbose = options.verbose |
---|
| 1254 | usersServerPort = options.port |
---|
| 1255 | usersServerIP = options.server |
---|
| 1256 | appLauncher = options.launcher |
---|
| 1257 | autologinMachine = options.autologin |
---|
| 1258 | loadState = options.load_state |
---|
| 1259 | autosave = options.autosave |
---|
| 1260 | |
---|
| 1261 | # set the overridden app launcher |
---|
| 1262 | if appLauncher != "": |
---|
| 1263 | setAppLauncher(appLauncher) |
---|
| 1264 | |
---|
| 1265 | # set the global variable for the SAGE SERVER |
---|
| 1266 | setSAGEServer(usersServerIP) |
---|
| 1267 | |
---|
| 1268 | # print some information about the system currently running |
---|
| 1269 | print "\nCurrently running:\n--------------------------" |
---|
| 1270 | print "SAGE UI version: ", VERSION |
---|
| 1271 | print "Python version: ", string.split(sys.version, "(", 1)[0] |
---|
| 1272 | print "wxPython version: "+str(wx.VERSION[0])+"."+str(wx.VERSION[1])+"."+str(wx.VERSION[2])+"."+str(wx.VERSION[3])+"\n" |
---|
| 1273 | |
---|
| 1274 | # read all the preferences |
---|
| 1275 | import preferences as prefs |
---|
| 1276 | prefs.readAllPreferences() |
---|
| 1277 | |
---|
| 1278 | app = SAGEui(usersServerIP, usersServerPort, verbose, autologinMachine, loadState) |
---|
| 1279 | app.MainLoop() |
---|
| 1280 | |
---|
| 1281 | |
---|
| 1282 | |
---|
| 1283 | |
---|
| 1284 | if __name__ == '__main__': |
---|
| 1285 | import sys, os |
---|
| 1286 | main(['', os.path.basename(sys.argv[0])] + sys.argv[1:]) |
---|
| 1287 | |
---|
| 1288 | |
---|
| 1289 | |
---|
| 1290 | |
---|
| 1291 | |
---|
| 1292 | |
---|