def OnInit(self): """ Initialize the application """ # If we have a Workshop Version, see if the version is still valid, report to the user and exit if not. # NOTE: This code just provides a user message and clean exit. Transana will still be disabled if this # code is removed. (This code is user-accessible on OS X!) if TransanaConstants.workshopVersion: import datetime t1 = TransanaConstants.startdate t2 = TransanaConstants.expirationdate t3 = time.localtime() t4 = datetime.datetime(t3[0], t3[1], t3[2], t3[3], t3[4]) if (t1 > t4) or (t2 < t4): dlg = Dialogs.ErrorDialog( None, "This copy of Transana is no longer valid.") dlg.ShowModal() dlg.Destroy return False # In wxPython, you used to be able to initialize the ConfigData object in the TransanaGlobal module, even though the # wx.App() hadn't been initialized yet. Moving from wxPython 2.8.1 to wxPython 2.8.9, this stopped being true # at least on the Mac. Therefore, we moved creation of the ConfigData object to here in the code. # However, there are MANY references to ConfigData being in the TransanaGlobal module, so that's where we'll keep it. TransanaGlobal.configData = ConfigData.ConfigData() # If we are running from a BUILD instead of source code ... if hasattr(sys, "frozen"): # or ('wxMac' in wx.PlatformInfo): # See if the Default Profile Path exists. If not ... if not os.path.exists( TransanaGlobal.configData.GetDefaultProfilePath()): # ... then create it (recursively). os.makedirs(TransanaGlobal.configData.GetDefaultProfilePath()) # Build the path for the error log path = os.path.join( TransanaGlobal.configData.GetDefaultProfilePath(), 'Transana_Error.log') # redirect output to the error log self.RedirectStdio(filename=path) # Put a startup indicator in the Error Log print "Transana started:", time.asctime() # If no Language is defined ... if TransanaGlobal.configData.language == '': # ... then we know this is the first startup for this user profile. Remember that! firstStartup = True # If language is known ... else: # ... then it's NOT first time startup. firstStartup = False # Now that we've loaded the Configuration Data, we can see if we need to alter the default encoding # If we're on Windows, single-user, using Russian, use KOI8r encoding instead of Latin-1, # Chinese uses big5, Japanese uses cp932, and Korean uses cp949 ## if ('wxMSW' in wx.PlatformInfo) and (TransanaConstants.singleUserVersion): ## if (TransanaGlobal.configData.language == 'ru'): ## TransanaGlobal.encoding = 'koi8_r' ## elif (TransanaGlobal.configData.language == 'zh'): ## TransanaGlobal.encoding = TransanaConstants.chineseEncoding ## elif (TransanaGlobal.configData.language == 'el'): ## TransanaGlobal.encoding = 'iso8859_7' ## elif (TransanaGlobal.configData.language == 'ja'): ## TransanaGlobal.encoding = 'cp932' ## elif (TransanaGlobal.configData.language == 'ko'): ## TransanaGlobal.encoding = 'cp949' # Use UTF-8 Encoding throughout Transana to allow maximum internationalization if ('unicode' in wx.PlatformInfo) and (wx.VERSION_STRING >= '2.6'): wx.SetDefaultPyEncoding('utf_8') # On OS/X, change the working directory to the directory the script is # running from, this is necessary for running from a bundle. if "__WXMAC__" in wx.PlatformInfo: if TransanaGlobal.programDir != '': os.chdir(TransanaGlobal.programDir) import MenuWindow # import Menu Window Object sys.excepthook = transana_excepthook # Define the system exception handler # First, determine the program name that should be displayed, single or multi-user if TransanaConstants.singleUserVersion: if TransanaConstants.proVersion: programTitle = _("Transana - Professional") else: programTitle = _("Transana - Standard") else: programTitle = _("Transana - Multiuser") # Ammend the program title for the Demo version if appropriate if TransanaConstants.demoVersion: programTitle += _(" - Demonstration") # Create the Menu Window TransanaGlobal.menuWindow = MenuWindow.MenuWindow( None, -1, programTitle) # Create the global transana graphics colors, once the ConfigData object exists. TransanaGlobal.transana_graphicsColorList = TransanaGlobal.getColorDefs( TransanaGlobal.configData.colorConfigFilename) # Set essential global color manipulation data structures once the ConfigData object exists. (TransanaGlobal.transana_colorNameList, TransanaGlobal.transana_colorLookup, TransanaGlobal.keywordMapColourSet ) = TransanaGlobal.SetColorVariables() # Add the RTF modules to the Python module search path. This allows # us to import from a directory other than the standard search paths # and the current directory/subdirectories. sys.path.append("rtf") # Load the Splash Screen graphic bitmap = TransanaImages.splash.GetBitmap() # We need to draw the Version Number onto the Splash Screen Graphic. # First, create a Memory DC memoryDC = wx.MemoryDC() # Select the bitmap into the Memory DC memoryDC.SelectObject(bitmap) # Build the Version label if TransanaConstants.singleUserVersion: if TransanaConstants.labVersion: versionLbl = _("Computer Lab Version") elif TransanaConstants.demoVersion: versionLbl = _("Demonstration Version") elif TransanaConstants.workshopVersion: versionLbl = _("Workshop Version") else: if TransanaConstants.proVersion: versionLbl = _("Professional Version") else: versionLbl = _("Standard Version") else: versionLbl = _("Multi-user Version") versionLbl += " %s" # Determine the size of the version text (verWidth, verHeight) = memoryDC.GetTextExtent( versionLbl % TransanaConstants.versionNumber) # Add the Version Number text to the Memory DC (and therefore the bitmap) memoryDC.DrawText(versionLbl % TransanaConstants.versionNumber, 370 - verWidth, 156) # Clear the bitmap from the Memory DC, thus freeing it to be displayed! memoryDC.SelectObject(wx.EmptyBitmap(10, 10)) # If the Splash Screen Graphic exists, display the Splash Screen for 4 seconds. # If not, raise an exception. if bitmap: # Mac requires a different style, as "STAY_ON_TOP" adds a header to the Splash Screen if "__WXMAC__" in wx.PlatformInfo: splashStyle = wx.SIMPLE_BORDER else: splashStyle = wx.SIMPLE_BORDER | wx.STAY_ON_TOP # If we have a Right-To-Left language ... if TransanaGlobal.configData.LayoutDirection == wx.Layout_RightToLeft: # ... we need to reverse the image direcion bitmap = bitmap.ConvertToImage().Mirror().ConvertToBitmap() splashPosition = wx.DefaultPosition ## This doesn't work. I have not been able to put the Splash Screen anywhere but on the Center of ## Monitor 0 (with wx.SPASH_CENTER_ON_SCREEN) or the upper left corner of Monitor 0 (without it). Bummer. ## # Get the Size and Position for the PRIMARY screen ## (x1, y1, w1, h1) = wx.Display(TransanaGlobal.configData.primaryScreen).GetClientArea() ## (x2, y2) = bitmap.GetSize() ## ## splashPosition = (int(float(w1) / 2.0) + x1 - int(float(x2) / 2.0), ## int(float(h1) / 2.0) + y1 - int(float(y2) / 2.0)) ## ## print "Splash Screen Position:" ## print TransanaGlobal.configData.primaryScreen ## print x1, y1, w1, h1 ## print x2, y2 ## print splashPosition ## print # Create the SplashScreen object splash = wx.SplashScreen( bitmap, wx.SPLASH_CENTER_ON_SCREEN | wx.SPLASH_TIMEOUT, 4000, None, -1, splashPosition, wx.DefaultSize, splashStyle) else: raise ImageLoadError, \ _("Unable to load Transana's splash screen image. Installation error?") wx.Yield() if DEBUG: print "Number of Monitors:", wx.Display.GetCount() for x in range(wx.Display.GetCount()): print " ", x, wx.Display(x).IsPrimary(), wx.Display( x).GetGeometry(), wx.Display(x).GetClientArea() print import DataWindow # import Data Window Object import VideoWindow # import Video Window Object # import Transcript Window Object if TransanaConstants.USESRTC: import TranscriptionUI_RTC as TranscriptionUI else: import TranscriptionUI import VisualizationWindow # import Visualization Window Object import exceptions # import exception handler (Python) # if we're running the multi-user version of Transana ... if not TransanaConstants.singleUserVersion: # ... import the Transana ChatWindow module import ChatWindow # Initialize all main application Window Objects # If we're running the Lab version OR we're on the Mac ... if TransanaConstants.labVersion or ('wxMac' in wx.PlatformInfo): # ... then pausing for 4 seconds delays the appearance of the Lab initial configuration dialog # or the Mac version login / database dialog until the Splash screen closes. time.sleep(4) # If we are running the Lab version ... if TransanaConstants.labVersion: # ... we want an initial configuration screen. Start by importing Transana's Option Settings dialog import OptionsSettings # Initialize all paths to BLANK for the lab version TransanaGlobal.configData.videoPath = '' TransanaGlobal.configData.visualizationPath = '' TransanaGlobal.configData.databaseDir = '' # Create the config dialog for the Lab initial configuration options = OptionsSettings.OptionsSettings( TransanaGlobal.menuWindow, lab=True) options.Destroy() wx.Yield() # If the databaseDir is blank, user pressed CANCEL ... if (TransanaGlobal.configData.databaseDir == ''): # ... and we should quit immediately, signalling failure return False # initialze a variable indicating database connection to False (assume the worst.) connectionEstablished = False # Let's trap the situation where the database folder is not available. try: # Start MySQL if using the embedded version if TransanaConstants.singleUserVersion: DBInterface.InitializeSingleUserDatabase() # If we get here, we've been successful! (NOTE that MU merely changes our default from False to True!) connectionEstablished = True except: if DEBUG: import traceback print sys.exc_info()[0], sys.exc_info()[1] traceback.print_exc(file=sys.stdout) msg = _( 'Transana is unable to access any Database at "%s".\nPlease check to see if this path is available.' ) if not TransanaConstants.labVersion: msg += '\n' + _( 'Would you like to restore the default Database path?') if ('unicode' in wx.PlatformInfo) and isinstance(msg, str): msg = unicode(msg, 'utf8') msg = msg % TransanaGlobal.configData.databaseDir if TransanaConstants.labVersion: dlg = Dialogs.ErrorDialog(None, msg) dlg.ShowModal() dlg.Destroy() return False # If we're on the Single-user version for Windows ... if TransanaConstants.singleUserVersion: # ... determine the file name for the data conversion information pickle file fs = os.path.join(TransanaGlobal.configData.databaseDir, '260_300_Convert.pkl') # If there is data in mid-conversion ... if os.path.exists(fs): # ... get the conversion data from the Pickle File f = file(fs, 'r') # exportedDBs is a dictionary containing the Transana-XML file name and the encoding of each DB to be imported self.exportedDBs = pickle.load(f) # Close the pickle file f.close() # Prompt the user about importing the converted data prompt = unicode( _("Transana has detected one or more databases ready for conversion.\nDo you want to convert those databases now?" ), 'utf8') tmpDlg = Dialogs.QuestionDialog(TransanaGlobal.menuWindow, prompt, _("Database Conversion")) result = tmpDlg.LocalShowModal() tmpDlg.Destroy() # If the user wants to do the conversion now ... if result == wx.ID_YES: # ... import Transana's XML Import code import XMLImport # Before we go further, let's make sure none of the conversion files have ALREADY been imported! # The 2.42 to 2.50 Data Conversion Utility shouldn't allow this, but it doesn't hurt to check. # Iterate through the conversion data for key in self.exportedDBs: # Determine the file path for the converted database newDBPath = os.path.join( TransanaGlobal.configData.databaseDir, key + '.db') # If the converted database ALREADY EXISTS ... if os.path.exists(newDBPath): # ... create an error message prompt = unicode( _('Database "%s" already exists.\nDatabase "%s" cannot be converted at this time.' ), 'utf8') # ... display an error message tmpDlg = Dialogs.ErrorDialog( None, prompt % (key, key)) tmpDlg.ShowModal() tmpDlg.Destroy() # If the converted database does NOT exist ... else: if 'wxMac' in wx.PlatformInfo: prompt = _( 'Converting "%s"\nThis process may take a long time, depending on how much data this database contains.\nWe cannot provide progress feedback on OS X. Please be patient.' ) progWarn = Dialogs.PopupDialog( None, _("Converting Databases"), prompt % key) # Create the Import Database, passing the database name so the user won't be prompted for one. DBInterface.establish_db_exists(dbToOpen=key, usePrompt=False) # Import the database. # First, create an Import Database dialog, but don't SHOW it. temp = XMLImport.XMLImport( TransanaGlobal.menuWindow, -1, _('Transana XML Import'), importData=self.exportedDBs[key]) # ... Import the requested data! temp.Import() # Close the Import Database dialog temp.Close() if 'wxMac' in wx.PlatformInfo: progWarn.Destroy() progWarn = None # Close the database that was just imported DBInterface.close_db() # Clear the current database name from the Config data TransanaGlobal.configData.database = '' # If we do NOT have a localhost key (which Lab version does not!) ... if not TransanaGlobal.configData.databaseList.has_key( 'localhost'): # ... let's create one so we can pass the converted database name! TransanaGlobal.configData.databaseList[ 'localhost'] = {} TransanaGlobal.configData.databaseList[ 'localhost']['dbList'] = [] # Update the database name TransanaGlobal.configData.database = key # Add the new (converted) database name to the database list TransanaGlobal.configData.databaseList[ 'localhost']['dbList'].append( key.encode('utf8')) # Start exception handling try: # If we're NOT in the lab version of Transana ... if not TransanaConstants.labVersion: # This is harder than it should be because of a combination of encoding and case-changing issues. # Let's iterate through the Version 2.5 "paths by database" config data for key2 in TransanaGlobal.configData.pathsByDB2.keys( ): # If we have a LOCAL database with a matching key to the database being imported ... if (key2[0] == '') and ( key2[1] == 'localhost' ) and (key2[2].decode('utf8').lower() == key): # Add the unconverted database's PATH values to the CONVERTED database's configuration! TransanaGlobal.configData.pathsByDB[('', 'localhost', key.encode('utf8'))] = \ {'visualizationPath' : TransanaGlobal.configData.pathsByDB2[key2]['visualizationPath'], 'videoPath' : TransanaGlobal.configData.pathsByDB2[key2]['videoPath']} # ... and we can stop looking break # Save the altered configuration data TransanaGlobal.configData.SaveConfiguration() # The Computer Lab version sometimes throws a KeyError except exceptions.KeyError: # If this comes up, we can ignore it. pass # Delete the Import File Information os.remove(fs) if DEBUG: print "Done importing Files" # We can only continue if we initialized the database OR are running MU. if connectionEstablished: # If a new database login fails three times, we need to close the program. # Initialize a counter to track that. logonCount = 1 # Flag if Logon succeeds loggedOn = False # Keep trying for three tries or until successful while (logonCount <= 3) and (not loggedOn): logonCount += 1 # Confirm the existence of the DB Tables, creating them if needed. # This method also calls the Username and Password Dialog if needed. # NOTE: The Menu Window must be created first to server as a parent for the Username and Password Dialog # called up by DBInterface. if DBInterface.establish_db_exists(): if DEBUG: print "Creating Data Window", # Create the Data Window # Data Window creation causes Username and Password Dialog to be displayed, # so it should be created before the Video Window self.dataWindow = DataWindow.DataWindow( TransanaGlobal.menuWindow) if DEBUG: print self.dataWindow.GetSize() print "Creating Video Window", # Create the Video Window self.videoWindow = VideoWindow.VideoWindow( TransanaGlobal.menuWindow) # Create the Transcript Window. If on the Mac, include the Close button. if DEBUG: print self.videoWindow.GetSize() print "Creating Transcript Window", self.transcriptWindow = TranscriptionUI.TranscriptionUI( TransanaGlobal.menuWindow, includeClose=('wxMac' in wx.PlatformInfo)) if DEBUG: print self.transcriptWindow.dlg.GetSize() print "Creating Visualization Window", # Create the Visualization Window self.visualizationWindow = VisualizationWindow.VisualizationWindow( TransanaGlobal.menuWindow) if DEBUG: print self.visualizationWindow.GetSize() print "Creating Control Object" # Create the Control Object and register all objects to be controlled with it self.ControlObject = ControlObject() self.ControlObject.Register( Menu=TransanaGlobal.menuWindow, Video=self.videoWindow, Transcript=self.transcriptWindow, Data=self.dataWindow, Visualization=self.visualizationWindow) # Set the active transcript self.ControlObject.activeTranscript = 0 # Register the ControlObject with all other objects to be controlled TransanaGlobal.menuWindow.Register( ControlObject=self.ControlObject) self.dataWindow.Register(ControlObject=self.ControlObject) self.videoWindow.Register(ControlObject=self.ControlObject) self.transcriptWindow.Register( ControlObject=self.ControlObject) self.visualizationWindow.Register( ControlObject=self.ControlObject) # Set the Application Top Window to the Menu Window (wxPython) self.SetTopWindow(TransanaGlobal.menuWindow) TransanaGlobal.resizingAll = True if DEBUG: print print "Before Showing Windows:" print " menu:\t\t", TransanaGlobal.menuWindow.GetRect( ) print " visual:\t", self.visualizationWindow.GetRect() print " video:\t", self.videoWindow.GetRect() print " trans:\t", self.transcriptWindow.dlg.GetRect() print " data:\t\t", self.dataWindow.GetRect() print print 'Heights:', self.transcriptWindow.dlg.GetRect( )[1] + self.transcriptWindow.dlg.GetRect( )[3], self.dataWindow.GetRect( )[1] + self.dataWindow.GetRect()[3] print if self.transcriptWindow.dlg.GetRect( )[1] + self.transcriptWindow.dlg.GetRect( )[3] > self.dataWindow.GetRect( )[1] + self.dataWindow.GetRect()[3]: self.dataWindow.SetRect((self.dataWindow.GetRect()[0], self.dataWindow.GetRect()[1], self.dataWindow.GetRect()[2], self.dataWindow.GetRect()[3] + \ (self.transcriptWindow.dlg.GetRect()[1] + self.transcriptWindow.dlg.GetRect()[3] - (self.dataWindow.GetRect()[1] + self.dataWindow.GetRect()[3])))) print "DataWindow Height Adjusted!" print " data:\t\t", self.dataWindow.GetRect() print # Show all Windows. TransanaGlobal.menuWindow.Show(True) if DEBUG: print "Showing Windows:" print " menu:", TransanaGlobal.menuWindow.GetRect() self.visualizationWindow.Show() if DEBUG: print " visualization:", self.visualizationWindow.GetRect( ) self.videoWindow.Show() if DEBUG: print " video:", self.videoWindow.GetRect( ), self.transcriptWindow.dlg.GetRect() self.transcriptWindow.Show() if DEBUG: print " transcript:", self.transcriptWindow.dlg.GetRect( ), self.dataWindow.GetRect() self.dataWindow.Show() if DEBUG: print " data:", self.dataWindow.GetRect( ), self.visualizationWindow.GetRect() # Get the size and position of the Visualization Window (x, y, w, h) = self.visualizationWindow.GetRect() if DEBUG: print print "Call 3", 'Visualization', w + x # Adjust the positions of all other windows to match the Visualization Window's initial position self.ControlObject.UpdateWindowPositions('Visualization', w + x + 1, YUpper=h + y + 1) TransanaGlobal.resizingAll = False loggedOn = True # If logon fails, inform user and offer to try again twice. elif logonCount <= 3: # Check to see if we have an SSL failure caused by insufficient data if (not TransanaConstants.singleUserVersion) and TransanaGlobal.configData.ssl and \ (TransanaGlobal.configData.sslClientCert == '' or TransanaGlobal.configData.sslClientKey == ''): # If so, inform the user prompt = _( "The information on the SSL tab is required to establish an SSL connection to the database.\nWould you like to try again?" ) # Otherwise ... else: # ... give a generic message about logon failure. prompt = _( 'Transana was unable to connect to the database.\nWould you like to try again?' ) dlg = Dialogs.QuestionDialog( TransanaGlobal.menuWindow, prompt, _('Transana Database Connection')) # If the user does not want to try again, set the counter to 4, which will cause the program to exit if dlg.LocalShowModal() == wx.ID_NO: logonCount = 4 # Clean up the Dialog Box dlg.Destroy() # If we successfully logged in ... if loggedOn: # ... save the configuration data that got us in TransanaGlobal.configData.SaveConfiguration() # if we're running the multi-user version of Transana and successfully connected to a database ... if not TransanaConstants.singleUserVersion and loggedOn: if DEBUG: print "Need to connect to MessageServer" # ... connect to the Message Server Here TransanaGlobal.socketConnection = ChatWindow.ConnectToMessageServer( ) # If the connections fails ... if TransanaGlobal.socketConnection == None: # ... signal that Transana should NOT start up! loggedOn = False else: # If Transana MU sits idle too long (30 - 60 minutes), people would sometimes get a # "Connection to Database Lost" error message even though MySQL was set to maintain the # connection for 8 hours. To try to address this, we will set up a Timer that will run # a simple query every 10 minutes to maintain the connection to the database. # Create the Connection Timer TransanaGlobal.connectionTimer = wx.Timer(self) # Bind the timer to its event self.Bind(wx.EVT_TIMER, self.OnTimer) # Tell the timer to fire every 10 minutes. # NOTE: If changing this value, it also needs to be changed in the ControlObjectClass.GetNewDatabase() method. TransanaGlobal.connectionTimer.Start(600000) if DEBUG: print "MessageServer connected!" # Check if the Database and Message Server are both using SSL and select the appropriate graphic self.dataWindow.UpdateSSLStatus(TransanaGlobal.configData.ssl and TransanaGlobal.chatIsSSL) # if this is the first time this user profile has used Transana ... if firstStartup and loggedOn: # ... create a prompt about looking at the Tutorial prompt = _( 'If this is your first time using Transana, the Transana Tutorial can help you learn how to use the program.' ) prompt += '\n\n' + _( 'Would you like to see the Transana Tutorial now?') # Display the Tutorial prompt in a Yes / No dialog tmpDlg = Dialogs.QuestionDialog(TransanaGlobal.menuWindow, prompt) # If the user says Yes ... if tmpDlg.LocalShowModal() == wx.ID_YES: # ... start the Tutorial self.ControlObject.Help('Welcome to the Transana Tutorial') if DEBUG: print print "Final Windows:" print " menu:\t\t", TransanaGlobal.menuWindow.GetRect() print " visual:\t", self.visualizationWindow.GetRect() print " video:\t", self.videoWindow.GetRect() print " trans:\t", self.transcriptWindow.dlg.GetRect() print " data:\t\t", self.dataWindow.GetRect() print else: loggedOn = False dlg = Dialogs.QuestionDialog(TransanaGlobal.menuWindow, msg, _('Transana Database Connection')) if dlg.LocalShowModal() == wx.ID_YES: TransanaGlobal.configData.databaseDir = os.path.join( TransanaGlobal.configData.GetDefaultProfilePath(), 'databases') TransanaGlobal.configData.SaveConfiguration() # Clean up the Dialog Box dlg.Destroy() return loggedOn
def __init__(self, parent): """ This is the Username, Password, Database Server, and Database Name Dialog """ # For single-user Transana, all we need it the Database Name. For multi-user Transana, # we need UserName, Password, Database Server, and Database Name. # First, let's set up some variables depending on whether we are in single-user or multi-user # mode. if TransanaConstants.singleUserVersion: # Dialog Title dlgTitle = _("Select Database") # Dialog Size dlgSize = (350, 40) # Instructions Text instructions = _( "Please enter the name of the database you wish to use.\nTo create a new database, type in a new database name.\n(Database names may contain only letters and numbers in a single word.)" ) if TransanaConstants.demoVersion: instructions = _( "Database selection has been disabled for the Demonstration Version.\n\nIn the full version of Transana, you can create as many separate\ndatabases as you want.\n" ) # Sizer Proportion for the instructions instProportion = 4 else: # Dialog Title dlgTitle = _("Username and Password") # Dialog Size dlgSize = (450, 320) # (350, 310) # Instructions Text instructions = _( "Please enter your MySQL username and password, as well \nas the names of the server and database you wish to use.\nTo create a new database, type in a new database name\n(if you have appropriate permissions.)\n(Database names may contain only letters and numbers in\na single word.)" ) # Macs don't need as much space for instructions as Windows machines do. if 'wxMac' in wx.PlatformInfo: # Sizer Proportion for the instructions instProportion = 4 else: # Sizer Proportion for the instructions instProportion = 6 # Define the main Dialog Box wx.Dialog.__init__(self, parent, -1, dlgTitle, size=dlgSize, style=wx.CAPTION | wx.RESIZE_BORDER) # To look right, the Mac needs the Small Window Variant. if "__WXMAC__" in wx.PlatformInfo: self.SetWindowVariant(wx.WINDOW_VARIANT_SMALL) # Create a BoxSizer for the main elements to go onto the Panel userPanelSizer = wx.BoxSizer(wx.VERTICAL) # If we are in the Multi-user Version ... if not TransanaConstants.singleUserVersion: notebook = wx.Notebook(self, -1, size=self.GetSizeTuple()) panelParent = notebook # Adding this line prevents an odd visual distortion in Arabic! notebook.SetBackgroundColour(wx.WHITE) else: panelParent = self # Place a Panel on the Dialog Box. All Controls will go on the Panel. # (Panels can have DefaultItems, enabling the desired "ENTER" key functionality. userPanel = wx.Panel(panelParent, -1, name='UserNamePanel') # Instructions Text lblIntro = wx.StaticText(userPanel, -1, instructions) # Add the Instructions to the Main Sizer # userPanelSizer.Add(lblIntro, instProportion, wx.EXPAND | wx.ALL, 10) userPanelSizer.Add(lblIntro, 0, wx.ALL, 10) # instProportion, wx.EXPAND | wx.ALL, 10) # Get the dictionary of defined database hosts and databases from the Configuration module self.Databases = TransanaGlobal.configData.databaseList # With release 2.30, we add the Port parameter for MU. This requires a change to the format of the # configuration data. Therefore, we need to examine the structure of the configuration data. # If it exists and the data type is a list, we need to update the structure of the existing data. if (len(self.Databases) > 0) and (type( self.Databases[self.Databases.keys()[0]]) == type([])): # Create a new Dictionary object newDatabases = {} # Iterate through the old dictionary object. For each database server ... for dbServer in self.Databases.keys(): # ... we need the database list AND the port. Port 3306 was the only option until this change #, so makes an adequate default. newDatabases[dbServer] = { 'dbList': self.Databases[dbServer], 'port': '3306' } # Replace the old config data with this modified version. self.Databases = newDatabases # The multi-user version has more fields than the single-user version. # If not the single-user version, put these fields on the form. if not TransanaConstants.singleUserVersion: # Let's use a FlexGridSizer for the data entry fields. # for MU, we want 5 rows with 2 columns # box2 = wx.FlexGridSizer(5, 2, 6, 0) # We want to be flexible horizontally # box2.SetFlexibleDirection(wx.HORIZONTAL) # We want the data entry fields to expand # box2.AddGrowableCol(1) # The proportion for the data entry portion of the screen should be 6 # box2Proportion = 0 # Use a BoxSizer instead of a FlexGridSizer. The FlexGridSizer isn't handling alternate font sizes # on Windows correctly. # box2 = wx.BoxSizer(wx.VERTICAL) # Create a Row Sizer for Username r1Sizer = wx.BoxSizer(wx.HORIZONTAL) # Username Label lblUsername = wx.StaticText(userPanel, -1, _("Username:"******"Password:"******"Host / Server:")) r3Sizer.Add(lblDBServer, 1, wx.ALL, 5) # If Databases has entries, use that to create the Choice List for the Database Servers list. if self.Databases.keys() != []: choicelist = self.Databases.keys() choicelist.sort() # If not, create a list with a blank entry else: choicelist = [''] # As of wxPython 2.9.5.0, Mac doesn't support wx.CB_SORT and gives an ugly message about it! if 'wxMac' in wx.PlatformInfo: style = wx.CB_DROPDOWN else: style = wx.CB_DROPDOWN | wx.CB_SORT # Host / Server Combo Box, with a list of servers from the Databases Object if appropriate self.chDBServer = wx.ComboBox(userPanel, -1, choices=choicelist, style=style) # Set the value to the default value provided by the Configuration Data self.chDBServer.SetValue(TransanaGlobal.configData.host) r3Sizer.Add(self.chDBServer, 4, wx.EXPAND | wx.ALL, 5) # box2.Add(r3Sizer, 0, wx.EXPAND) userPanelSizer.Add(r3Sizer, 0, wx.EXPAND) # Define the Selection, SetFocus and KillFocus events for the Host / Server Combo Box wx.EVT_COMBOBOX(self, self.chDBServer.GetId(), self.OnServerSelect) # NOTE: These events don't work on the MAC! There appears to be a wxPython bug. See wxPython ticket # 9862 wx.EVT_KILL_FOCUS(self.chDBServer, self.OnServerKillFocus) # Create a Row Sizer for Port r4Sizer = wx.BoxSizer(wx.HORIZONTAL) # Define the Port TextCtrl and its KillFocus event lblPort = wx.StaticText(userPanel, -1, _("Port:")) r4Sizer.Add(lblPort, 1, wx.ALL, 5) self.txtPort = wx.TextCtrl(userPanel, -1, TransanaGlobal.configData.dbport, style=wx.TE_LEFT) r4Sizer.Add(self.txtPort, 4, wx.EXPAND | wx.ALL, 5) # box2.Add(r4Sizer, 0, wx.EXPAND) userPanelSizer.Add(r4Sizer, 0, wx.EXPAND) # This wx.EVT_SET_FOCUS is a poor attempt to compensate for wxPython bug # 9862 if 'wxMac' in wx.PlatformInfo: self.txtPort.Bind(wx.EVT_SET_FOCUS, self.OnServerKillFocus) self.txtPort.Bind(wx.EVT_KILL_FOCUS, self.OnPortKillFocus) # # Let's add the MU controls we've created to the Data Entry Sizer # box2.AddMany([(lblUsername, 1, wx.RIGHT, 10), # (self.txtUsername, 2, wx.EXPAND), # (lblPassword, 1, wx.RIGHT, 10), # (self.txtPassword, 2, wx.EXPAND), # (lblDBServer, 1, wx.RIGHT, 10), # (self.chDBServer, 2, wx.EXPAND), # (lblPort, 1, wx.RIGHT, 10), # (self.txtPort, 2, wx.EXPAND) # ]) # else: # # For single-user Transana, we only need one row with two columns # box2 = wx.FlexGridSizer(1, 2, 0, 0) # # We want the grid to grow horizontally # box2.SetFlexibleDirection(wx.HORIZONTAL) # # We want the data entry field to grow # box2.AddGrowableCol(1) # # Since there's only one row, the sizer proportion can be small. # box2Proportion = 2 # The proportion for the data entry portion of the screen should be 6 # box2Proportion = 0 # Use a BoxSizer instead of a FlexGridSizer. The FlexGridSizer isn't handling alternate font sizes # on Windows correctly. # box2 = wx.BoxSizer(wx.VERTICAL) # The rest of the controls are needed for both single- and multi-user versions. # Create a Row Sizer for Port r5Sizer = wx.BoxSizer(wx.HORIZONTAL) # Databases Label lblDBName = wx.StaticText(userPanel, -1, _("Database:")) r5Sizer.Add(lblDBName, 1, wx.ALL, 5) # If a Host is defined, get the list of Databases defined for that host. # The single-user version ... if TransanaConstants.singleUserVersion: # ... uses "localhost" as the server. DBServerName = 'localhost' # The multi-user version ... else: # ... uses whatever is selected in the DBServer Choice Box. DBServerName = self.chDBServer.GetValue() # There's a problem with wxPython's wxComboBox. It sets the drop-down height to the number of options # in the initial choicelist, and keeps that even if the choicelist is changed. # To get around this, we give it a fake choice list with enough entries, then populate it later. choicelist = ['', '', '', '', ''] # As of wxPython 2.9.5.0, Mac doesn't support wx.CB_SORT and gives an ugly message about it! if 'wxMac' in wx.PlatformInfo: style = wx.CB_DROPDOWN else: style = wx.CB_DROPDOWN | wx.CB_SORT # Database Combo Box self.chDBName = wx.ComboBox(userPanel, -1, choices=choicelist, style=style) # If we're in the Demo version ... if TransanaConstants.demoVersion: # ... then "Demonstration" is the only allowable Database Name self.chDBName.Clear() self.chDBName.Append("Demonstration") self.chDBName.SetValue("Demonstration") self.chDBName.Enable(False) # If we're NOT in the Demo version ... else: # If some Database have been defined... if len(self.Databases) >= 1: # ... Use the Databases object to get the list of Databases for the # identified Server if DBServerName != '': choicelist = self.Databases[DBServerName]['dbList'] # Sort the Database List choicelist.sort() else: choicelist = [''] # Clear out the control's Choices ... self.chDBName.Clear() # ... and populate them with the appropriate values for choice in choicelist: if ('unicode' in wx.PlatformInfo) and (isinstance( choice, str)): choice = unicode(choice, 'utf8') # TransanaGlobal.encoding) self.chDBName.Append(choice) # if the configured database isn't in the database list, don't show it! # This can happen if you have a Russian database name but change away from Russian encoding # by changing languages during the session. ## print ## print "UsernameandPasswordClass.__init__():" ## print TransanaGlobal.configData.database.encode('utf8'), type(TransanaGlobal.configData.database) ## for x in range(len(choicelist)): ## print choicelist[x], type(choicelist[x]), TransanaGlobal.configData.database.encode('utf8') == choicelist[x] ## print TransanaGlobal.configData.database.encode('utf8') in choicelist, choicelist.index(TransanaGlobal.configData.database.encode('utf8')) ## print ## ## # If we're on the Mac ... ## if 'wxMac' in wx.PlatformInfo: ## # ... SetStringSelection is broken, so we locate the string's item number and use SetSelection! ## if TransanaGlobal.configData.database in choicelist: ## self.chDBName.SetSelection(choicelist.index(TransanaGlobal.configData.database.encode('utf8'))) # (self.chDBName.GetItems().index(TransanaGlobal.configData.database.encode('utf8'))) ## else: if self.chDBName.FindString( TransanaGlobal.configData.database) != wx.NOT_FOUND: # Set the value to the default value provided by the Configuration Data self.chDBName.SetStringSelection( TransanaGlobal.configData.database) r5Sizer.Add(self.chDBName, 4, wx.EXPAND | wx.ALL, 5) # box2.Add(r5Sizer, 0, wx.EXPAND) userPanelSizer.Add(r5Sizer, 0, wx.EXPAND) # Define the SetFocus and KillFocus events for the Database Combo Box wx.EVT_KILL_FOCUS(self.chDBName, self.OnNameKillFocus) # Weird Mac bug ... Can't select all Database Names from the list sometimes. So, if Mac ... if 'wxMac' in wx.PlatformInfo: # ... add a Combo Box Event handler for the Database Name selection self.chDBName.Bind(wx.EVT_COMBOBOX, self.OnNameSelect) # # Add the Database name fields to the Data Entry sizer # box2.AddMany([(lblDBName, 1, wx.RIGHT, 10), # (self.chDBName, 2, wx.EXPAND) # ]) # Now add the Data Entry sizer to the Main sizer # userPanelSizer.Add(box2, box2Proportion, wx.EXPAND | wx.LEFT | wx.RIGHT, 10) # userPanelSizer.Add(box2, 0, wx.LEFT | wx.RIGHT, 10) # If we are in the Multi-user Version ... if not TransanaConstants.singleUserVersion: # Add an SSL checkbox to the Username panel self.sslCheck = wx.CheckBox(userPanel, -1, _("Use SSL") + " ", style=wx.CHK_2STATE | wx.ALIGN_RIGHT) # If SSL is True in the configuration file ... if TransanaGlobal.configData.ssl: # ... check the box self.sslCheck.SetValue(True) # Add a Spacer userPanelSizer.Add((0, 5)) # Add the checkbox to the Username panel userPanelSizer.Add(self.sslCheck, 0, wx.LEFT | wx.ALIGN_LEFT, 5) # Add a Spacer userPanelSizer.Add((0, 10)) # Add the User Panel to the first Notebook tab notebook.AddPage(userPanel, _("Database"), True) # Import the Transana OptionsSettings module, needed for the Message Server panel import OptionsSettings # Create teh Message Server Panel (which parents the MessageServer and MessageServerPort TextCtrls) self.messageServerPanel = OptionsSettings.MessageServerPanel( notebook, name='Username.MessageServerPanel') # Add the Message Server Panel to the second Notebook notebook.AddPage(self.messageServerPanel, _("Message Server"), False) # Create a Panel for the SSL information sslPanel = wx.Panel(notebook, -1, size=notebook.GetSizeTuple(), name='UsernameandPasswordClass.sslPanel') # Create a Sizer for the SSL Panel sslSizer = wx.BoxSizer(wx.VERTICAL) # Get wxPython's Standard Paths sp = wx.StandardPaths.Get() # Set the initial SSL Directory to the user's Document Directory self.sslDir = sp.GetDocumentsDir() # Add the Client Certificate File to the SSL Tab lblClientCert = wx.StaticText( sslPanel, -1, _("Database Server SSL Client Certificate File"), style=wx.ST_NO_AUTORESIZE) # Add the label to the Panel Sizer sslSizer.Add(lblClientCert, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10) # Add a spacer sslSizer.Add((0, 3)) # Add the Client Certificate File TextCtrl to the SSL Tab self.sslClientCert = wx.TextCtrl( sslPanel, -1, TransanaGlobal.configData.sslClientCert) # Add the element to the Panel Sizer sslSizer.Add(self.sslClientCert, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10) # Add a Browse button for the Client Certificate File self.sslClientCertBrowse = wx.Button(sslPanel, -1, _("Browse")) # Add the button to the Sizer sslSizer.Add(self.sslClientCertBrowse, 0, wx.LEFT | wx.BOTTOM, 10) # Bind the button to the event processor self.sslClientCertBrowse.Bind(wx.EVT_BUTTON, self.OnSSLButton) # Add a spacer sslSizer.Add((0, 5)) # Add the Client Key File to the SSL Tab lblClientKey = wx.StaticText( sslPanel, -1, _("Database Server SSL Client Key File"), style=wx.ST_NO_AUTORESIZE) # Add the label to the Panel Sizer sslSizer.Add(lblClientKey, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10) # Add a spacer sslSizer.Add((0, 3)) # Add the Client Key File TextCtrl to the SSL Tab self.sslClientKey = wx.TextCtrl( sslPanel, -1, TransanaGlobal.configData.sslClientKey) # Add the element to the Panel Sizer sslSizer.Add(self.sslClientKey, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10) # Add a Browse button for the Client Key File self.sslClientKeyBrowse = wx.Button(sslPanel, -1, _("Browse")) # Add the button to the Sizer sslSizer.Add(self.sslClientKeyBrowse, 0, wx.LEFT | wx.BOTTOM, 10) # Bind the button to the event processor self.sslClientKeyBrowse.Bind(wx.EVT_BUTTON, self.OnSSLButton) # Add the Message Server Certificate File to the SSL Tab lblMsgSrvCert = wx.StaticText( sslPanel, -1, _("Message Server SSL Certificate File"), style=wx.ST_NO_AUTORESIZE) # Add the label to the Panel Sizer sslSizer.Add(lblMsgSrvCert, 0, wx.LEFT | wx.RIGHT | wx.TOP, 10) # Add a spacer sslSizer.Add((0, 3)) # Add the Message Server Certificate File TextCtrl to the SSL Tab self.sslMsgSrvCert = wx.TextCtrl( sslPanel, -1, TransanaGlobal.configData.sslMsgSrvCert) # Add the element to the Panel Sizer sslSizer.Add(self.sslMsgSrvCert, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, 10) # Add a Browse button for the Message Server Certificate File self.sslMsgSrvCertBrowse = wx.Button(sslPanel, -1, _("Browse")) # Add the button to the Sizer sslSizer.Add(self.sslMsgSrvCertBrowse, 0, wx.LEFT | wx.BOTTOM, 10) # Bind the button to the event processor self.sslMsgSrvCertBrowse.Bind(wx.EVT_BUTTON, self.OnSSLButton) # Set the SSL Panel's Sizer sslPanel.SetSizer(sslSizer) # Turn on AutoLayout sslPanel.SetAutoLayout(True) # Lay out the panel sslPanel.Layout() # Add the SSL Panel as the third Notebook tab notebook.AddPage(sslPanel, _("SSL"), False) # Create another sizer for the buttons, with a horizontal orientation buttonSizer = wx.BoxSizer(wx.HORIZONTAL) # If this is NOT the Demo version ... if not TransanaConstants.demoVersion: # Define the "Delete Database" Button btnDeleteDatabase = wx.Button(self, -1, _("Delete Database")) self.Bind(wx.EVT_BUTTON, self.OnDeleteDatabase, btnDeleteDatabase) # Define the "OK" button btnOK = wx.Button(self, wx.ID_OK, _("OK")) # Make the OK button the default. (This one works on Linux, while the next line doesn't!) btnOK.SetDefault() # Define the Default Button for the dialog. This allows the "ENTER" key # to fire the OK button regardless of which widget has focus on the form. self.SetDefaultItem(btnOK) # Define the Cancel Button btnCancel = wx.Button(self, wx.ID_CANCEL, _("Cancel")) # Define the "OK" button if not TransanaConstants.demoVersion: # Add the Delete Database button to the lower left corner buttonSizer.Add( btnDeleteDatabase, 3, wx.ALIGN_LEFT | wx.ALIGN_BOTTOM | wx.LEFT | wx.BOTTOM, 10) # Lets have some space between this button and the others. buttonSizer.Add((30, 1), 1, wx.EXPAND) # Add the OK button to the lower right corner buttonSizer.Add( btnOK, 2, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM | wx.RIGHT | wx.BOTTOM, 10) # Add the Cancel button to the lower right corner, bumping the OK button to the left buttonSizer.Add( btnCancel, 2, wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM | wx.RIGHT | wx.BOTTOM, 10) # Lay out the panel and the form, request AutoLayout for both. userPanel.Layout() userPanel.SetAutoLayout(True) # Set the main Panel's sizer to the main sizer and "fit" it. userPanel.SetSizer(userPanelSizer) userPanel.Fit() # Remember the size of the UserPanel at this point, to determine what DISPLAY TEXT size is selected in Windows userPanelSize = userPanel.GetSize() # Let's stick the panel on a sizer to fit in the Dialog panSizer = wx.BoxSizer(wx.VERTICAL) if TransanaConstants.singleUserVersion: panSizer.Add(userPanel, 1, wx.EXPAND) else: panSizer.Add(notebook, 1, wx.EXPAND) panSizer.Add((0, 3)) # Add the Button sizer to the main sizer panSizer.Add(buttonSizer, 0, wx.EXPAND) self.SetSizer(panSizer) self.Layout() self.SetAutoLayout(True) self.Fit() # Lay out the dialog box, and tell it to resize automatically self.Layout() # If we are in the Multi-user Version ... if not TransanaConstants.singleUserVersion: # ... if we're using Small or Normal fonts ... if userPanelSize[1] < 350: # ... this size should work for the dialog self.SetSize((self.GetSize()[0], 410)) # ... but if we're using Medium fonts ... else: # ... we need a larger dialog size self.SetSize((520, 500)) # Set minimum window size dlgSize = self.GetSizeTuple() self.SetSizeHints(dlgSize[0], dlgSize[1]) # Center the dialog on the screen self.CentreOnScreen() # The Mac version needs the focus to be set explicitly. # If we're running single-user Transana ... if TransanaConstants.singleUserVersion: # ... focus on the Database name, which is the only field self.chDBName.SetFocus() # If we're running multi-user Transana ... else: # ... and we don't know the username ... if self.txtUsername.GetValue() == '': # ... then focus on the username ... self.txtUsername.SetFocus() # ... but if we DO know the username ... else: # ... then let's focus on the password instead. self.txtPassword.SetFocus() # Show the Form modally, process if OK selected if self.ShowModal() == wx.ID_OK: # Save the Values if TransanaConstants.singleUserVersion: self.Username = '' self.Password = '' self.DBServer = 'localhost' self.Port = '3306' self.SSL = False self.MessageServer = '' self.MessageServerPort = '' self.SSLClientCert = '' self.SSLClientKey = '' self.SSLMsgSrvCert = '' else: self.Username = self.txtUsername.GetValue() self.Password = self.txtPassword.GetValue() self.DBServer = self.chDBServer.GetValue() self.Port = self.txtPort.GetValue() self.SSL = self.sslCheck.IsChecked() self.MessageServer = self.messageServerPanel.messageServer.GetValue( ) self.MessageServerPort = self.messageServerPanel.messageServerPort.GetValue( ) self.SSLClientCert = self.sslClientCert.GetValue() self.SSLClientKey = self.sslClientKey.GetValue() self.SSLMsgSrvCert = self.sslMsgSrvCert.GetValue() self.DBName = self.chDBName.GetValue() # the EVT_KILL_FOCUS for the Combo Boxes isn't getting called on the Mac. Let's call it manually here if "__WXMAC__" in wx.PlatformInfo: self.OnNameKillFocus(None) # Since the list could have been changed here, pass it back to the Configuration module so the appropriate # data will be saved during program shutdown TransanaGlobal.configData.databaseList = self.Databases else: self.Username = '' self.Password = '' self.DBServer = '' self.DBName = '' self.Port = '' self.SSL = False self.MessageServer = '' self.MessageServerPort = '' self.SSLClientCert = '' self.SSLClientKey = '' self.SSLMsgSrvCert = '' return None