comparison orpg/networking/mplay_server_gui.py @ 0:4385a7d0efd1 grumpy-goblin

Deleted and repushed it with the 'grumpy-goblin' branch. I forgot a y
author sirebral
date Tue, 14 Jul 2009 16:41:58 -0500
parents
children c97c641a76fd
comparison
equal deleted inserted replaced
-1:000000000000 0:4385a7d0efd1
1 #!/usr/bin/env python
2 #
3 # OpenRPG Server Graphical Interface
4 # GNU General Public License
5 #
6
7 __appname__=' OpenRPG GUI Server v0.7 '
8 __version__='$Revision: 1.26 $'[11:-2]
9 __cvsinfo__='$Id: mplay_server_gui.py,v 1.26 2007/11/06 00:32:39 digitalxero Exp $'[5:-2]
10 __doc__="""
11 OpenRPG Server Graphical Interface
12 """
13
14 import os
15 import sys
16 import time
17 import types
18 import orpg.dirpath
19 import orpg.systempath
20 from orpg.orpg_wx import *
21 import webbrowser
22 from threading import Thread
23 from meta_server_lib import post_server_data, remove_server
24 from mplay_server import mplay_server
25
26 # Constants ######################################
27 SERVER_RUNNING = 1
28 SERVER_STOPPED = 0
29 MENU_START_SERVER = wx.NewId()
30 MENU_STOP_SERVER = wx.NewId()
31 MENU_EXIT = wx.NewId()
32 MENU_REGISTER_SERVER = wx.NewId()
33 MENU_UNREGISTER_SERVER = wx.NewId()
34 MENU_START_PING_PLAYERS = wx.NewId()
35 MENU_STOP_PING_PLAYERS = wx.NewId()
36 MENU_PING_INTERVAL = wx.NewId()
37
38 # Add our menu id's for our right click popup
39 MENU_PLAYER_BOOT = wx.NewId()
40 MENU_PLAYER_CREATE_ROOM = wx.NewId()
41 MENU_PLAYER_SEND_MESSAGE = wx.NewId()
42 MENU_PLAYER_SEND_ROOM_MESSAGE = wx.NewId()
43 MENU_PLAYER_SEND_SERVER_MESSAGE = wx.NewId()
44
45 # Our new event type that gets posted from one
46 # thread to another
47 wxEVT_LOG_MESSAGE = wx.NewEventType()
48 wxEVT_FUNCTION_MESSAGE = wx.NewEventType()
49
50 # Our event connector -- wxEVT_LOG_MESSAGE
51 EVT_LOG_MESSAGE = wx.PyEventBinder(wxEVT_LOG_MESSAGE, 1)
52
53 # Our event connector -- wxEVT_FUNCTION_MESSAGE
54 EVT_FUNCTION_MESSAGE = wx.PyEventBinder(wxEVT_FUNCTION_MESSAGE, 1)
55
56 # Utils ##########################################
57 def format_bytes(b):
58 f = ['b', 'Kb', 'Mb', 'Gb']
59 i = 0
60 while i < 3:
61 if b < 1024:
62 return str(b) + f[i]
63 else:
64 b = b/1024
65 i += 1
66 return str(b) + f[3]
67
68 # wxEVT_LOG_MESSAGE
69 # MessageLogEvent ###############################
70 class MessageLogEvent(wx.PyEvent):
71 def __init__( self, message ):
72 wx.PyEvent.__init__( self )
73 self.SetEventType(wxEVT_LOG_MESSAGE)
74 self.message = message
75
76 # wxEVT_TUPLE_MESSAGE
77 # MessageLogEvent ###############################
78 class MessageFunctionEvent(wx.PyEvent):
79 def __init__( self, func, message ):
80 wx.PyEvent.__init__( self )
81 self.SetEventType(wxEVT_FUNCTION_MESSAGE)
82 self.func = func
83 self.message = message
84
85 # ServerConfig Object ############################
86 class ServerConfig:
87 """ This class contains configuration
88 setting used to control the server.
89 """
90
91 def __init__(self, owner ):
92 """ Loads default configuration settings.
93 """
94 OPENRPG_PORT = 9775
95 self.owner = owner
96
97 def load_xml(self, xml):
98 """ Load configuration from XML data.
99 xml (xml) -- xml string to parse
100 """
101 pass
102
103 def save_xml(self):
104 """ Returns XML file representing
105 the active configuration.
106 """
107 pass
108
109 # Server Monitor #################################
110
111 class ServerMonitor(Thread):
112 """ Monitor thread for GameServer. """
113 def __init__(self, cb, conf, name, pwd):
114 """ Setup the server. """
115 Thread.__init__(self)
116 self.cb = cb
117 self.conf = conf
118 self.serverName = name
119 self.bootPwd = pwd
120
121 def log(self, mesg):
122 if type(mesg) == types.TupleType:
123 func, msg = mesg
124 event = MessageFunctionEvent( func, msg )
125 else:
126 event = MessageLogEvent( mesg )
127 wx.PostEvent( self.conf.owner, event )
128 del event
129
130 def run(self):
131 """ Start the server. """
132 self.server = mplay_server(self.log, self.serverName )
133 self.server.initServer(bootPassword=self.bootPwd, reg="No")
134 self.alive = 1
135 while self.alive:
136 time.sleep(3)
137
138 def stop(self):
139 """ Stop the server. """
140 self.server.kill_server()
141 self.alive = 0
142
143 # GUI Server #####################################
144 # Parent = notebook
145 # Main = GUI
146 class Connections(wx.ListCtrl):
147 def __init__( self, parent, main ):
148 wx.ListCtrl.__init__( self, parent, -1, wx.DefaultPosition, wx.DefaultSize, wx.LC_REPORT|wx.SUNKEN_BORDER|wx.EXPAND|wx.LC_HRULES )
149 self.main = main
150 self.roomList = { "0" : "Lobby" }
151 self._imageList = wx.ImageList( 16, 16, False )
152 img = wx.Image(orpg.dirpath.dir_struct["icon"]+"player.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap()
153 self._imageList.Add( img )
154 img = wx.Image(orpg.dirpath.dir_struct["icon"]+"player-whisper.gif", wx.BITMAP_TYPE_GIF).ConvertToBitmap()
155 self._imageList.Add( img )
156 self.SetImageList( self._imageList, wx.IMAGE_LIST_SMALL )
157
158 # Set The columns
159 self.InsertColumn(0, "ID")
160 self.InsertColumn(1, "Player")
161 self.InsertColumn(2, "Status")
162 self.InsertColumn(3, "Room")
163 self.InsertColumn(4, "Version")
164 self.InsertColumn(5, "Role")
165 self.InsertColumn(6, "IP")
166 self.InsertColumn(7, "Ping")
167
168 # Set the column widths
169 self.AutoAjust()
170
171 # Build our pop up menu to do cool things with the players in the list
172 self.menu = wx.Menu()
173 self.menu.SetTitle( "Player Menu" )
174 self.menu.Append( MENU_PLAYER_BOOT, "Boot Player" )
175 self.menu.AppendSeparator()
176 self.menu.Append( MENU_PLAYER_SEND_MESSAGE, "Send Message" )
177 self.menu.Append( MENU_PLAYER_SEND_SERVER_MESSAGE, "Broadcast Server Message" )
178
179 # Associate our events
180 self.Bind(wx.EVT_RIGHT_DOWN, self.OnPopupMenu)
181 self.Bind(wx.EVT_MENU, self.OnPopupMenuItem, id=MENU_PLAYER_BOOT)
182 self.Bind(wx.EVT_MENU, self.OnPopupMenuItem, id=MENU_PLAYER_SEND_MESSAGE)
183 self.Bind(wx.EVT_MENU, self.OnPopupMenuItem, id=MENU_PLAYER_SEND_ROOM_MESSAGE)
184 self.Bind(wx.EVT_MENU, self.OnPopupMenuItem, id=MENU_PLAYER_SEND_SERVER_MESSAGE)
185
186 def add(self, player):
187 i = self.InsertImageStringItem( 0, player["id"], 0 )
188 self.SetStringItem( i, 1, self.stripHtml( player["name"] ) )
189 self.SetStringItem( i, 2, self.stripHtml( player["status"] ) )
190 self.SetStringItem( i, 3, "ROOM" )
191 self.SetStringItem( i, 4, self.stripHtml( player["version"] ) )
192 self.SetStringItem( i, 5, self.stripHtml( player["role"] ) )
193 self.SetStringItem( i, 6, self.stripHtml( player["ip"] ) )
194 self.SetStringItem (i, 7, "PING" )
195 self.SetItemData( i, int(player["id"]) )
196 self.AutoAjust()
197
198 def remove(self, id):
199 i = self.FindItemData( -1, int(id) )
200 self.DeleteItem( i )
201 self.AutoAjust()
202
203 def AutoAjust(self):
204 self.SetColumnWidth(0, -1)
205 self.SetColumnWidth(1, -1)
206 self.SetColumnWidth(2, -1)
207 self.SetColumnWidth(3, -1)
208 self.SetColumnWidth(4, -1)
209 self.SetColumnWidth(5, -1)
210 self.SetColumnWidth(6, -1)
211 self.SetColumnWidth(7, -1)
212 self.Refresh()
213
214 def update(self, player):
215 i = self.FindItemData( -1, int(player["id"]) )
216 if i > -1:
217 self.SetStringItem(i, 1, player["name"])
218 self.SetStringItem(i, 2, self.stripHtml( player["status"] ) )
219 self.AutoAjust()
220 else:
221 self.add(player)
222
223 def updateRoom( self, data ):
224 (from_id, id) = data
225 i = self.FindItemData( -1, int(from_id) )
226 self.SetStringItem( i, 3, self.roomList[id] )
227 self.SetStringItem( i, 5, "Lurker")
228 self.Refresh()
229
230 def setPlayerRole( self, id, role ):
231 i = self.FindItemData( -1, int(id) )
232 self.SetStringItem( i, 5, role )
233
234 def stripHtml( self, name ):
235 ret_string = ""
236 x = 0
237 in_tag = 0
238 for x in range( len(name) ):
239 if name[x] == "<" or name[x] == ">" or in_tag == 1 :
240 if name[x] == "<" :
241 in_tag = 1
242 elif name[x] == ">" :
243 in_tag = 0
244 else :
245 pass
246 else :
247 ret_string = ret_string + name[x]
248 return ret_string
249
250 # When we right click, cause our popup menu to appear
251 def OnPopupMenu( self, event ):
252 pos = wx.Point( event.GetX(), event.GetY() )
253 (item, flag) = self.HitTest( pos )
254 if item > -1:
255 self.selectedItem = item
256 self.PopupMenu( self.menu, pos )
257
258 # Process the events associated with our popup menu
259 def OnPopupMenuItem( self, event ):
260 # if we are not running, the player list is empty anyways
261 if self.main.STATUS == SERVER_RUNNING:
262 menuItem = event.GetId()
263 playerID = str( self.GetItemData( self.selectedItem ) )
264 idList = self.main.server.server.groups
265 groupID = 0
266 if menuItem == MENU_PLAYER_BOOT:
267 print "booting player: ", playerID
268 self.main.server.server.del_player( playerID, groupID )
269 self.main.server.server.check_group( playerID, groupID )
270 self.remove( playerID )
271 elif menuItem == MENU_PLAYER_SEND_MESSAGE:
272 print "send a message..."
273 msg = self.GetMessageInput( "Send a message to player" )
274 if len(msg):
275 self.main.server.server.send( msg, playerID, str(groupID) )
276 # Leave this in for now.
277 # elif menuItem == MENU_PLAYER_SEND_TO_ROOM:
278 # print "Send message to room..."
279 # msg = self.GetMessageInput( "Send message to room of this player")
280 # if len(msg):
281 # self.main.server.server.send_to_group( 0, GroupID, msg )
282
283 elif menuItem == MENU_PLAYER_SEND_SERVER_MESSAGE:
284 print "broadcast a message..."
285 msg = self.GetMessageInput( "Broadcast Server Message" )
286 # If we got a message back, send it
287 if len(msg):
288 self.main.server.server.broadcast( msg )
289
290 def GetMessageInput( self, title ):
291 prompt = "Please enter the message you wish to send:"
292 msg = wx.TextEntryDialog(self, prompt, title)
293 msg.ShowModal()
294 msg.Destroy()
295 return msg.GetValue()
296
297 class ServerGUI(wx.Frame):
298 STATUS = SERVER_STOPPED
299
300 def __init__(self, parent, id, title):
301 wx.Frame.__init__(self, parent, id, title, size = (760, 560) )
302 if wx.Platform == '__WXMSW__':
303 icon = wx.Icon( orpg.dirpath.dir_struct["icon"]+'WAmisc9.ico', wx.BITMAP_TYPE_ICO )
304 else:
305 icon = wx.Icon( orpg.dirpath.dir_struct["icon"]+'connect.gif', wx.BITMAP_TYPE_GIF )
306 self.SetIcon(icon)
307 self.serverName = "Server Name"
308 self.bootPwd = ""
309
310 # Register our events to process -- notice the custom event handler
311 self.Bind(wx.EVT_CLOSE, self.OnExit)
312 self.Bind(EVT_LOG_MESSAGE, self.OnLogMessage)
313 self.Bind(EVT_FUNCTION_MESSAGE, self.OnFunctionMessage)
314
315 # Creat GUI
316 self.build_menu()
317 self.build_body()
318 self.build_status()
319
320 # Server Callbacks
321 cb = {}
322 cb["log"] = self.Log
323 cb["connect"] = self.OnConnect
324 cb["disconnect"] = self.OnDisconnect
325 cb["update"] = self.OnUpdatePlayer
326 cb["data_recv"] = self.OnDataRecv
327 cb["data_sent"] = self.OnDataSent
328 cb["create_group"] = self.OnCreateGroup
329 cb["delete_group"] = self.OnDeleteGroup
330 cb["join_group"] = self.OnJoinGroup
331 cb["role"] = self.OnSetRole
332 self.callbacks = cb
333
334 # Misc.
335 self.conf = ServerConfig(self)
336 self.total_messages_received = 0
337 self.total_data_received = 0
338 self.total_messages_sent = 0
339 self.total_data_sent = 0
340
341 ### Build GUI ############################################
342
343 def build_menu(self):
344 """ Build the GUI menu. """
345 self.mainMenu = wx.MenuBar()
346 # File Menu
347 menu = wx.Menu()
348 # Start
349 menu.Append( MENU_START_SERVER, 'Start', 'Start server.')
350 self.Bind(wx.EVT_MENU, self.OnStart, id=MENU_START_SERVER)
351 # Stop
352 menu.Append( MENU_STOP_SERVER, 'Stop', 'Shutdown server.')
353 self.Bind(wx.EVT_MENU, self.OnStop, id=MENU_STOP_SERVER)
354 # Exit
355 menu.AppendSeparator()
356 menu.Append( MENU_EXIT, 'E&xit', 'Exit application.')
357 self.Bind(wx.EVT_MENU, self.OnExit, id=MENU_EXIT)
358 self.mainMenu.Append(menu, '&Server')
359 # Registration Menu
360 menu = wx.Menu()
361 # Register
362 menu.Append( MENU_REGISTER_SERVER, 'Register', 'Register with OpenRPG server directory.')
363 self.Bind(wx.EVT_MENU, self.OnRegister, id=MENU_REGISTER_SERVER)
364 # Unregister
365 menu.Append( MENU_UNREGISTER_SERVER, 'Unregister', 'Unregister from OpenRPG server directory.')
366 self.Bind(wx.EVT_MENU, self.OnUnregister, id=MENU_UNREGISTER_SERVER)
367 # Add the registration menu
368 self.mainMenu.Append( menu, '&Registration' )
369 # Server Configuration Menu
370 menu = wx.Menu()
371 # Ping Connected Players
372 menu.Append( MENU_START_PING_PLAYERS, 'Start Ping', 'Ping players to validate remote connection.' )
373 self.Bind(wx.EVT_MENU, self.PingPlayers, id=MENU_START_PING_PLAYERS)
374 # Stop Pinging Connected Players
375 menu.Append( MENU_STOP_PING_PLAYERS, 'Stop Ping', 'Stop validating player connections.' )
376 self.Bind(wx.EVT_MENU, self.StopPingPlayers, id=MENU_STOP_PING_PLAYERS)
377 # Set Ping Interval
378 menu.Append( MENU_PING_INTERVAL, 'Ping Interval', 'Change the ping interval.' )
379 self.Bind(wx.EVT_MENU, self.ConfigPingInterval, id=MENU_PING_INTERVAL)
380 self.mainMenu.Append( menu, '&Configuration' )
381 # Add the menus to the main menu bar
382 self.SetMenuBar( self.mainMenu )
383 # Disable register, unregister & stop server by default
384 self.mainMenu.Enable( MENU_STOP_SERVER, False )
385 self.mainMenu.Enable( MENU_REGISTER_SERVER, False )
386 self.mainMenu.Enable( MENU_UNREGISTER_SERVER, False )
387 # Disable the ping menu items
388 self.mainMenu.Enable( MENU_START_PING_PLAYERS, False )
389 self.mainMenu.Enable( MENU_STOP_PING_PLAYERS, False )
390 self.mainMenu.Enable( MENU_PING_INTERVAL, False )
391
392 def build_body(self):
393 """ Create the ViewNotebook and logger. """
394 splitter = wx.SplitterWindow(self, -1, style=wx.NO_3D | wx.SP_3D)
395 nb = wx.Notebook( splitter, -1 )
396 self.conns = Connections( nb, self )
397 nb.AddPage( self.conns, "Players" )
398 #Not sure why this is Remarked TaS - Sirebral
399 #nb.AddPage( self.conns, "Rooms" )
400 #self.msgWindow = HTMLMessageWindow( nb )
401 #nb.AddPage( self.msgWindow, "Messages" )
402
403 log = wx.TextCtrl(splitter, -1, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL)
404 wx.Log.SetActiveTarget( wx.LogTextCtrl(log) )
405 splitter.SplitHorizontally(nb, log, 400)
406 splitter.SetMinimumPaneSize(40)
407 self.nb = nb
408 self.log = log
409
410 def build_status(self):
411 """ Create status bar and set defaults. """
412 sb = wx.StatusBar(self, -1)
413 sb.SetFieldsCount(5)
414 sb.SetStatusWidths([-1, 115, 115, 65, 200])
415 sb.SetStatusText("Sent: 0", 1)
416 sb.SetStatusText("Recv: 0", 2)
417 sb.SetStatusText("Stopped", 3)
418 sb.SetStatusText("Unregistered", 4)
419 self.SetStatusBar(sb)
420 self.sb = sb
421
422 def show_error(self, mesg, title = "Error"):
423 """ Display an error.
424 mesg (str) -- error message to display
425 title (str) -- title of window
426 """
427 dlg = wx.MessageDialog(self, mesg, title, wx.OK | wx.ICON_EXCLAMATION)
428 dlg.ShowModal()
429 dlg.Destroy()
430
431
432 # Event handler for out logging event
433 def OnLogMessage( self, event ):
434 self.Log( event.message )
435
436 # Event handler for out logging event
437 def OnFunctionMessage( self, event ):
438 self.callbacks[event.func]( event.message )
439
440 ### Server Callbacks #####################################
441 def Log(self, log):
442 wx.LogMessage(str(log))
443
444 def OnConnect(player, self, data):
445 self.conns.add(player)
446
447 def OnDisconnect(self, id):
448 self.conns.remove(id)
449
450 def OnUpdatePlayer(self, data):
451 self.conns.update(data)
452
453 def OnDataSent(self, bytes):
454 self.total_messages_sent += 1
455 self.total_data_sent += bytes
456 self.sb.SetStatusText("Sent: %s (%d)" % (format_bytes(self.total_data_sent), self.total_messages_sent), 1)
457
458 def OnDataRecv(self, bytes):
459 self.total_messages_received += 1
460 self.total_data_received += bytes
461 self.sb.SetStatusText("Recv: %s (%d)" % (format_bytes(self.total_data_received), self.total_messages_received), 2)
462
463 def OnCreateGroup( self, data ):
464 print "room list: ", self.conns.roomList
465 self.conns.roomList[id] = name
466 (id, name) = data
467 print "room list: ", self.conns.roomList
468
469 def OnDeleteGroup( self, data ):
470 (from_id, id) = data
471 # del self.conns.roomList[id]
472 print "OnDeleteGroup room list: ", self.conns.roomList, id
473
474 def OnJoinGroup( self, data ):
475 self.conns.updateRoom( data )
476
477 def OnSetRole( self, data ):
478 (id, role) = data
479 self.conns.setPlayerRole( id, role )
480
481 ### Misc. ################################################
482 def OnStart(self, event = None):
483 """ Start server. """
484 if self.STATUS == SERVER_STOPPED:
485 serverNameEntry = wx.TextEntryDialog( self, "Please Enter The Server Name You Wish To Use:",
486 "Server's Name", self.serverName, wx.OK|wx.CANCEL|wx.CENTRE )
487 if serverNameEntry.ShowModal() == wx.ID_OK:
488 self.serverName = serverNameEntry.GetValue()
489 serverPasswordEntry = wx.TextEntryDialog(self, "Please Enter The Server Admin Password:",
490 "Server's Password", self.bootPwd, wx.OK|wx.CANCEL|wx.CENTRE)
491 if serverPasswordEntry.ShowModal() == wx.ID_OK:
492 self.bootPwd = serverPasswordEntry.GetValue()
493 if len(self.serverName):
494 wx.BeginBusyCursor()
495 self.server = ServerMonitor(self.callbacks, self.conf, self.serverName, self.bootPwd)
496 self.server.start()
497 self.STATUS = SERVER_RUNNING
498 self.sb.SetStatusText("Running", 3)
499 self.SetTitle(__appname__ + "- (running) - (unregistered)")
500 self.mainMenu.Enable( MENU_START_SERVER, False )
501 self.mainMenu.Enable( MENU_STOP_SERVER, True )
502 self.mainMenu.Enable( MENU_REGISTER_SERVER, True )
503 wx.EndBusyCursor()
504 else:
505 self.show_error("Server is already running.", "Error Starting Server")
506
507 def OnStop(self, event = None):
508 """ Stop server. """
509 if self.STATUS == SERVER_RUNNING:
510 self.OnUnregister()
511 self.server.stop()
512 self.STATUS = SERVER_STOPPED
513 self.sb.SetStatusText("Stopped", 3)
514 self.SetTitle(__appname__ + "- (stopped) - (unregistered)")
515 self.mainMenu.Enable( MENU_STOP_SERVER, False )
516 self.mainMenu.Enable( MENU_START_SERVER, True )
517 self.mainMenu.Enable( MENU_REGISTER_SERVER, False )
518 self.mainMenu.Enable( MENU_UNREGISTER_SERVER, False )
519 # Delete any items that are still in the player list
520 self.conns.DeleteAllItems()
521
522 def OnRegister(self, event = None):
523 """ Call into mplay_server's register() function.
524 This will begin registerThread(s) to keep server
525 registered with configured metas
526 """
527 if len( self.serverName ):
528 wx.BeginBusyCursor()
529 self.server.server.register(self.serverName)
530 self.sb.SetStatusText( ("%s" % (self.serverName)), 4 )
531 self.mainMenu.Enable( MENU_REGISTER_SERVER, False )
532 self.mainMenu.Enable( MENU_UNREGISTER_SERVER, True )
533 self.mainMenu.Enable( MENU_STOP_SERVER, False )
534 self.SetTitle(__appname__ + "- (running) - (registered)")
535 wx.EndBusyCursor()
536
537 def OnUnregister(self, event = None):
538 """ Call into mplay_server's unregister() function.
539 This will kill any registerThreads currently running
540 and result in the server being de-listed
541 from all metas
542 """
543 wx.BeginBusyCursor()
544 self.server.server.unregister()
545 self.sb.SetStatusText( "Unregistered", 4 )
546 self.mainMenu.Enable( MENU_UNREGISTER_SERVER, False )
547 self.mainMenu.Enable( MENU_REGISTER_SERVER, True )
548 self.mainMenu.Enable( MENU_STOP_SERVER, True )
549 self.SetTitle(__appname__ + "- (running) - (unregistered)")
550 wx.EndBusyCursor()
551
552 def PingPlayers( self, event = None ):
553 "Ping all players that are connected at a periodic interval, detecting dropped connections."
554 wx.BeginBusyCursor()
555 wx.Yield()
556 wx.EndBusyCursor()
557
558 def StopPingPlayers( self, event = None ):
559 "Stop pinging connected players."
560
561 def ConfigPingInterval( self, event = None ):
562 "Configure the player ping interval. Note that all players are pinged on a single timer."
563
564 def OnExit(self, event = None):
565 """ Quit the program. """
566 self.OnStop()
567 wx.CallAfter(self.Destroy)
568
569 class ServerGUIApp(wx.App):
570 def OnInit(self):
571 # Make sure our image handlers are loaded before we try to display anything
572 wx.InitAllImageHandlers()
573 self.splash = wx.SplashScreen(wx.Bitmap(orpg.dirpath.dir_struct["icon"]+'splash.gif'),
574 wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT,
575 2000,
576 None)
577 self.splash.Show(True)
578 wx.Yield()
579 wx.CallAfter(self.AfterSplash)
580 return True
581
582 def AfterSplash(self):
583 self.splash.Close(True)
584 frame = ServerGUI(None, -1, __appname__ + "- (stopped) - (unregistered)")
585 frame.Show(True)
586 frame.Raise()
587 self.SetTopWindow(frame)
588
589 class HTMLMessageWindow(wx.html.HtmlWindow):
590 "Widget used to present user to admin messages, in HTML format, to the server administrator"
591
592 # Init using the derived from class
593 def __init__( self, parent ):
594 wx.html.HtmlWindow.__init__( self, parent )
595 def OnLinkClicked( self, ref ):
596 "Open an external browser to resolve our About box links!!!"
597 href = ref.GetHref()
598 webbrowser.open( href )
599
600 if __name__ == '__main__':
601 app = ServerGUIApp(0)
602 app.MainLoop()