def suggestUpdate(self, confirmationDlg=False): """Query user about whether to update (if it's possible to do the update) """ if self.latest == None: #we haven't checked for updates yet self.latest = self.getLatestInfo() if self.latest == -1: return -1 #failed to find out about updates #have found 'latest'. Is it newer than running version? if self.latest['version'] > self.runningVersion and not ( self.app.prefs.appData['skipVersion'] == self.latest['version']): if self.latest['lastUpdatable'] <= self.runningVersion: #go to the updating window confirmDlg = SuggestUpdateDialog(self.latest, self.runningVersion) resp = confirmDlg.ShowModal() confirmDlg.Destroy() #what did the user ask us to do? if resp == wx.ID_CANCEL: return 0 #do nothing if resp == wx.ID_NO: self.app.prefs.appData['skipVersion'] = self.latest[ 'version'] self.app.prefs.saveAppData() return 0 #do nothing if resp == wx.ID_YES: self.doUpdate() else: #the latest version needs a full install, rather than an autoupdate msg = "PsychoPy v%s is available (you are running %s).\n\n" % ( self.latest['version'], self.runningVersion) msg += "This version is too big an update to be handled automatically.\n" msg += "Please fetch the latest version from www.psychopy.org and install manually." confirmDlg = dialogs.MessageDialog(parent=None, message=msg, type='Warning', title='PsychoPy updates') confirmDlg.cancelBtn.SetLabel('Go to downloads') confirmDlg.cancelBtn.SetDefault() confirmDlg.noBtn.SetLabel('Go to changelog') confirmDlg.yesBtn.SetLabel('Later') resp = confirmDlg.ShowModal() confirmDlg.Destroy() if resp == wx.ID_CANCEL: self.app.followLink(url=self.app.urls['downloads']) if resp == wx.ID_NO: self.app.followLink(url=self.app.urls['changelog']) elif not confirmationDlg: #do nothing return 0 else: msg = "You are running the latest version of PsychoPy (%s). " % ( self.runningVersion) confirmDlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title='PsychoPy updates') confirmDlg.ShowModal() return -1
def getLatestInfo(self, warnMsg=False): #open page URL = "http://www.psychopy.org/version.txt" try: page = urllib2.urlopen(URL) #proxies except: if warnMsg: msg="Couldn't connect to psychopy.org to check for updates. \n"+\ "Check internet settings (and proxy setting in PsychoPy Preferences)." confirmDlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title='PsychoPy updates') confirmDlg.ShowModal() return -1 #parse update file as a dictionary latest = {} for line in page.readlines(): #in some odd circumstances (wifi hotspots) you might successfully fetch a #page that is not the correct URL but a redirect if line.find(':') == -1: return -1 #this will succeed if every line has a key key, keyInfo = line.split(':') latest[key] = keyInfo.replace('\n', '').replace('\r', '') return latest
def onLogin(self, event): """ Check credentials and login """ if not havePyosf: dialogs.MessageDialog( parent=self.parent, type='Warning', title=_translate("pyosf not found"), message=_translate("You need pyosf to " "log in to Open Science Framework"), ) return None username = self.username.GetValue() pword = self.password.GetValue() rememberMe = bool(self.rememberMe.GetValue()) try: session = pyosf.Session(username=username, password=pword, remember_me=rememberMe) self.app.osf_session = session self.updateStatus(_translate("Successful authentication"), color=(0, 170, 0)) time.sleep(0.5) self.Destroy() except pyosf.AuthError: self.updateStatus(_translate("Failed to Authenticate. " "Check username/password"), color=(255, 0, 0))
def setPrefsFromCtrls(self): # extract values, adjust as needed: # a) strip() to remove whitespace # b) case-insensitive match for Cmd+ at start of string # c) reverse-map locale display names to canonical names (ja_JP) re_cmd2ctrl = re.compile('^Cmd\+', re.I) for sectionName in self.prefsCfg.keys(): for prefName in self.prefsSpec[sectionName].keys(): if prefName in ['version']: #any other prefs not to show? continue ctrlName = sectionName + '.' + prefName ctrl = self.ctrls[ctrlName] thisPref = ctrl.getValue() # remove invisible trailing whitespace: if hasattr(thisPref, 'strip'): thisPref = thisPref.strip() # regularize the display format for keybindings if sectionName == 'keyBindings': thisPref = thisPref.replace(' ', '') thisPref = '+'.join( [part.capitalize() for part in thisPref.split('+')]) if platform.system() == 'Darwin': # key-bindings were displayed as 'Cmd+O', revert to 'Ctrl+O' internally thisPref = re_cmd2ctrl.sub('Ctrl+', thisPref) self.prefsCfg[sectionName][prefName] = thisPref #make sure list values are converted back to being lists (from strings) if self.prefsSpec[sectionName][prefName].startswith('list'): try: # if thisPref is not a null string, do eval() to get a list. if thisPref == '': newVal = thisPref else: newVal = eval(thisPref) except: # if eval() failed, show warning dialog and return try: pLabel = _localized[prefName] sLabel = _localized[sectionName] except: pLabel = prefName sLabel = sectionName warnDlg = dialogs.MessageDialog( parent=self, message=_translate( 'Invalid value in "%(pref)s" ("%(section)s" Tab)' ) % { 'pref': pLabel, 'section': sLabel }, type='Info', title=_translate('Error')) resp = warnDlg.ShowModal() return if type(newVal) != list: self.prefsCfg[sectionName][prefName] = [newVal] else: self.prefsCfg[sectionName][prefName] = newVal self.app.prefs.saveUserPrefs() #includes a validation
def getLatestInfo(self, warnMsg=False): #open page latest=getLatestVersionInfo() if latest==-1: msg=_translate("Couldn't connect to psychopy.org to check for updates. \n")+\ _translate("Check internet settings (and proxy setting in PsychoPy Preferences).") confirmDlg = dialogs.MessageDialog(parent=None,message=msg,type='Info', title=_translate('PsychoPy updates')) confirmDlg.ShowModal() return latest
def onBtnFindPhotometer(self, event): # safer to get by index, but GetStringSelection will work for # nonlocalized techincal names: photName = self.ctrlPhotomType.GetStringSelection() # not sure how photPort = self.ctrlPhotomPort.GetValue().strip() # [0] == Scan all ports if not photPort or photPort == self._photomChoices[0]: photPort = None elif photPort.isdigit(): photPort = int(photPort) # search all ports self.comPortLabel.SetLabel(_translate('Scanning ports...')) self.Update() self.photom = hardware.findPhotometer(device=photName, ports=photPort) if self.photom is not None and self.photom.OK: self.btnFindPhotometer.Disable() self.btnCalibrateGamma.Enable(True) self.btnTestGamma.Enable(True) if hasattr(self.photom, 'getLastSpectrum'): self.btnCalibrateColor.Enable(True) msg = _translate('%(photomType)s found on %(photomPort)s') self.comPortLabel.SetLabel(msg % {'photomType': self.photom.type, 'photomPort': self.photom.portString}) else: self.comPortLabel.SetLabel(_translate('No photometers found')) self.photom = None # does this device need a dark calibration? if (hasattr(self.photom, 'getNeedsCalibrateZero') and self.photom.getNeedsCalibrateZero()): # prompt user if we need a dark calibration for the device if self.photom.getNeedsCalibrateZero(): dlg = wx.Dialog(self, title=_translate( 'Dark calibration of ColorCAL')) msg = _translate('Your ColorCAL needs to be calibrated first.' ' Please block all light from getting into ' 'the lens and press OK.') while self.photom.getNeedsCalibrateZero(): txt = _translate('Dark calibration of ColorCAL') dlg = dialogs.MessageDialog(self, message=msg, title=txt, type='Info') # info dlg has only an OK button resp = dlg.ShowModal() if resp == wx.ID_CANCEL: self.photom = None self.comPortLabel.SetLabel('') return 0 elif resp == wx.ID_OK: self.photom.calibrateZero() # this failed at least once. Try again. msg = _translate('Try again. Cover the lens fully and ' 'press OK')
def onNew(self, event): """Create a new project for OSF """ if self.app.osf_session.user_id: projEditor = ProjectEditor() projEditor.Show() else: infoDlg = dialogs.MessageDialog(parent=None, type='Info', message=_translate( "You need to log in" " to create a project")) infoDlg.Show()
def onDeleteCalib(self, event): calToDel = self.ctrlCalibList.GetStringSelection() #warn user that data will be lost dlg = dialogs.MessageDialog(parent=self, message=_translate('Are you sure you want to delete this calibration? (cannot be undone)'), type='Warning') if dlg.ShowModal() == wx.ID_YES: #delete it self.currentMon.delCalib(calToDel) #load most recent calibration instead self.onChangeCalibSelection(event=None, newCalib=-1)#this will load calibration "-1" (last calib) self.updateCalibList() dlg.Destroy()
def onCloseWindow(self, event): if self.unSavedMonitor: #warn user that data will be lost dlg = dialogs.MessageDialog(self,message=_translate('Save changes to monitor settings before quitting?'),type='Warning') resp = dlg.ShowModal() if resp == wx.ID_CANCEL: return 1 #return before quitting elif resp == wx.ID_YES: #save then quit self.currentMon.saveMon() elif resp == wx.ID_NO: pass #don't save just quit dlg.Destroy() self.onCopyMon() # save current monitor name to clipboard self.Destroy()
def onBtnFindPhotometer(self, event): photName = self.ctrlPhotomType.GetStringSelection() photPort = self.ctrlPhotomPort.GetValue().strip() if not photPort or photPort == "Scan all ports": photPort = None elif photPort.isdigit(): photPort = int(photPort) #search all ports self.comPortLabel.SetLabel('Scanning ports...') self.Update() self.photom = hardware.findPhotometer(device=photName, ports=photPort) if self.photom is not None and self.photom.OK: self.btnFindPhotometer.Disable() self.btnCalibrateGamma.Enable(True) self.btnTestGamma.Enable(True) if hasattr(self.photom, 'getLastSpectrum'): self.btnCalibrateColor.Enable(True) self.comPortLabel.SetLabel( '%s found on %s' % (self.photom.type, self.photom.portString)) else: self.comPortLabel.SetLabel('No photometers found') self.photom = None #does this device need a dark calibration? if hasattr(self.photom, 'getNeedsCalibrateZero' ) and self.photom.getNeedsCalibrateZero(): #prompt user if we need a dark calibration for the device if self.photom.getNeedsCalibrateZero(): dlg = wx.Dialog(self, title='Dark calibration of ColorCAL') msg='Your ColorCAL needs to be calibrated first. ' +\ 'Please block all light from getting into the lens and press OK.' while self.photom.getNeedsCalibrateZero(): dlg = dialogs.MessageDialog( self, message=msg, title='Dark calibration of ColorCAL', type='Info') #info dlg has only an OK button resp = dlg.ShowModal() if resp == wx.ID_CANCEL: self.photom = None self.comPortLabel.SetLabel('') return 0 elif resp == wx.ID_OK: self.photom.calibrateZero() #this failed at least once. Try again. msg = 'Try again. Cover the lens fully and press OK'
def onDeleteMon(self, event): monToDel = self.currentMonName dlg = dialogs.MessageDialog(parent=self, message=_translate('Are you sure you want to delete all details for %s? (cannot be undone)') % monToDel, type='Warning') response = dlg.ShowModal() dlg.Destroy() if response == wx.ID_YES: #delete it monitorFileName = os.path.join(monitors.monitorFolder, monToDel+".calib") os.remove(monitorFileName) self.currentMon=None self.currentMonName=None self.updateMonList() #load most recent calibration instead self.onChangeMonSelection(event=None)#this will load calibration "-1" (last calib) self.updateCalibList()
def onChangeMonSelection(self, event): if self.unSavedMonitor: if self.currentMonName == self.ctrlMonList.GetStringSelection(): # it didnt' really change return 1 # warn user that data will be lost msg = _translate('Save changes to monitor?') dlg = dialogs.MessageDialog(self, msg, type='Warning') resp = dlg.ShowModal() dlg.Destroy() if resp == wx.ID_CANCEL: # revert and return self.ctrlMonList.SetStringSelection(self.currentMonName) return False # return before quitting elif resp == wx.ID_YES: # save then change self.currentMon.saveMon() elif resp == wx.ID_NO: pass # don't save just change self.currentMonName = self.ctrlMonList.GetStringSelection() self.loadMonitor(self.currentMonName)
def onInit(self, showSplash=True, testMode=False): """ :Parameters: testMode: bool If set to True then startup wizard won't appear and stdout/stderr won't be redirected to the Coder """ self.version = psychopy.__version__ self.SetAppName('PsychoPy2') # import localization after wx: from psychopy.app import localization # needed by splash screen self.localization = localization self.locale = localization.wxlocale self.locale.AddCatalog(self.GetAppName()) # set default paths and prefs self.prefs = psychopy.prefs if self.prefs.app['debugMode']: logging.console.setLevel(logging.DEBUG) # indicates whether we're running for testing purposes self.testMode = testMode self.osf_session = None if showSplash: # show splash screen splashFile = os.path.join( self.prefs.paths['resources'], 'psychopySplash.png') splashBitmap = wx.Image(name=splashFile).ConvertToBitmap() splash = AS.AdvancedSplash(None, bitmap=splashBitmap, timeout=3000, style=AS.AS_TIMEOUT | wx.FRAME_SHAPED, shadowcolour=wx.RED) # transparency? splash.SetTextPosition((10, 240)) splash.SetText(_translate(" Loading libraries...")) else: splash = None # SLOW IMPORTS - these need to be imported after splash screen starts # but then that they end up being local so keep track in self if splash: splash.SetText(_translate(" Loading PsychoPy2...")) from psychopy.compatibility import checkCompatibility # import coder and builder here but only use them later from psychopy.app import coder, builder, dialogs, urls self.keys = self.prefs.keys self.prefs.pageCurrent = 0 # track last-viewed page, can return there self.IDs = IDStore() self.urls = urls.urls self.quitting = False # check compatibility with last run version (before opening windows) self.firstRun = False if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData: # must be before 1.74.00 last = self.prefs.appData['lastVersion'] = '1.73.04' self.firstRun = True else: last = self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: self.firstrunWizard() # setup links for URLs # on a mac, don't exit when the last frame is deleted, just show menu if sys.platform == 'darwin': self.menuFrame = MenuFrame(parent=None, app=self) # get preferred view(s) from prefs and previous view if self.prefs.app['defaultView'] == 'last': mainFrame = self.prefs.appData['lastFrame'] else: # configobjValidate should take care of this situation allowed = ['last', 'coder', 'builder', 'both'] if self.prefs.app['defaultView'] in allowed: mainFrame = self.prefs.app['defaultView'] else: self.prefs.app['defaultView'] = 'both' mainFrame = 'both' # fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts = self.prefs.appData['coder']['prevFiles'] else: scripts = [] appKeys = list(self.prefs.appData['builder'].keys()) if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in appKeys): exps = self.prefs.appData['builder']['prevFiles'] else: exps = [] # then override the prev files by command options and passed files if len(sys.argv) > 1: if sys.argv[1] == __name__: # program was executed as "python.exe PsychoPyIDE.py %1' args = sys.argv[2:] else: # program was executed as "PsychoPyIDE.py %1' args = sys.argv[1:] # choose which frame to start with if args[0] in ['builder', '--builder', '-b']: mainFrame = 'builder' args = args[1:] # can remove that argument elif args[0] in ['coder', '--coder', '-c']: mainFrame = 'coder' args = args[1:] # can remove that argument # did we get .py or .psyexp files? elif args[0][-7:] == '.psyexp': mainFrame = 'builder' exps = [args[0]] elif args[0][-3:] == '.py': mainFrame = 'coder' scripts = [args[0]] else: args = [] self.dpi = int(wx.GetDisplaySize()[0] / float(wx.GetDisplaySizeMM()[0]) * 25.4) if not (50 < self.dpi < 120): self.dpi = 80 # dpi was unreasonable, make one up if sys.platform == 'win32': # wx.SYS_DEFAULT_GUI_FONT is default GUI font in Win32 self._mainFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) else: self._mainFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) self._codeFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) self._codeFont.SetFaceName(self.prefs.coder['codeFont']) # removed Aug 2017: on newer versions of wx (at least on mac) # this looks too big # if hasattr(self._mainFont, 'Larger'): # # Font.Larger is available since wyPython version 2.9.1 # # PsychoPy still supports 2.8 (see ensureMinimal above) # self._mainFont = self._mainFont.Larger() # self._codeFont.SetPointSize( # self._mainFont.GetPointSize()) # unify font size # create both frame for coder/builder as necess if splash: splash.SetText(_translate(" Creating frames...")) self.coder = None self.copiedRoutine = None self.copiedCompon = None self._allFrames = [] # ordered; order updated with self.onNewTopWindow if mainFrame in ['both', 'coder']: self.showCoder(fileList=scripts) if mainFrame in ['both', 'builder']: self.showBuilder(fileList=exps) # send anonymous info to www.psychopy.org/usage.php # please don't disable this, it's important for PsychoPy's development self._latestAvailableVersion = None self.updater = None prefsConn = self.prefs.connections if prefsConn['checkForUpdates'] or prefsConn['allowUsageStats']: connectThread = threading.Thread( target=connections.makeConnections, args=(self,)) connectThread.start() # query github in the background to populate a local cache about # what versions are available for download: from psychopy.tools import versionchooser as vc versionsThread = threading.Thread(target=vc._remoteVersions, args=(True,)) versionsThread.start() ok, msg = checkCompatibility(last, self.version, self.prefs, fix=True) # tell the user what has changed if not ok and not self.firstRun and not self.testMode: title = _translate("Compatibility information") dlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title=title) dlg.ShowModal() if self.prefs.app['showStartupTips'] and not self.testMode: tipFile = os.path.join( self.prefs.paths['resources'], _translate("tips.txt")) tipIndex = self.prefs.appData['tipIndex'] tp = wx.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() if self.prefs.connections['checkForUpdates']: self.Bind(wx.EVT_IDLE, self.checkUpdates) else: self.Bind(wx.EVT_IDLE, self.onIdle) # doing this once subsequently enables the app to open & switch among # wx-windows on some platforms (Mac 10.9.4) with wx-3.0: if wx.version() >= '3.0' and sys.platform == 'darwin': _Showgui_Hack() # returns ~immediately, no display # focus stays in never-land, so bring back to the app: if mainFrame in ['both', 'builder']: self.showBuilder() else: self.showCoder() return True
def onInit(self, showSplash=True, testMode=False): """This is launched immediately *after* the app initialises with wx :Parameters: testMode: bool """ self.SetAppName('PsychoPy3') # Single instance check is done here prior to loading any GUI stuff. # This permits one instance of PsychoPy from running at any time. # Clicking on files will open them in the extant instance rather than # loading up a new one. # # Inter-process messaging is done via a memory-mapped file created by # the first instance. Successive instances will write their args to # this file and promptly close. The main instance will read this file # periodically for data and open and file names stored to this buffer. # # This uses similar logic to this example: # https://github.com/wxWidgets/wxPython-Classic/blob/master/wx/lib/pydocview.py # Create the memory-mapped file if not present, this is handled # differently between Windows and UNIX-likes. if wx.Platform == '__WXMSW__': tfile = tempfile.TemporaryFile(prefix="ag", suffix="tmp") fno = tfile.fileno() self._sharedMemory = mmap.mmap(fno, self.mmap_sz, "shared_memory") else: tfile = open( os.path.join( tempfile.gettempdir(), tempfile.gettempprefix() + self.GetAppName() + '-' + wx.GetUserId() + "AGSharedMemory"), 'w+b') # insert markers into the buffer tfile.write(b"*") tfile.seek(self.mmap_sz) tfile.write(b" ") tfile.flush() fno = tfile.fileno() self._sharedMemory = mmap.mmap(fno, self.mmap_sz) # use wx to determine if another instance is running self._singleInstanceChecker = wx.SingleInstanceChecker( self.GetAppName() + '-' + wx.GetUserId(), tempfile.gettempdir()) # If another instance is running, message our args to it by writing the # path the the buffer. if self._singleInstanceChecker.IsAnotherRunning(): # Message the extant running instance the arguments we want to # process. args = sys.argv[1:] # if there are no args, tell the user another instance is running if not args: errMsg = "Another instance of PsychoPy is already running." errDlg = wx.MessageDialog(None, errMsg, caption="PsychoPy Error", style=wx.OK | wx.ICON_ERROR, pos=wx.DefaultPosition) errDlg.ShowModal() errDlg.Destroy() self.quit(None) # serialize the data data = pickle.dumps(args) # Keep alive until the buffer is free for writing, this allows # multiple files to be opened in succession. Times out after 5 # seconds. attempts = 0 while attempts < 5: # try to write to the buffer self._sharedMemory.seek(0) marker = self._sharedMemory.read(1) if marker == b'\0' or marker == b'*': self._sharedMemory.seek(0) self._sharedMemory.write(b'-') self._sharedMemory.write(data) self._sharedMemory.seek(0) self._sharedMemory.write(b'+') self._sharedMemory.flush() break else: # wait a bit for the buffer to become free time.sleep(1) attempts += 1 else: if not self.testMode: # error that we could not access the memory-mapped file errMsg = \ "Cannot communicate with running PsychoPy instance!" errDlg = wx.MessageDialog(None, errMsg, caption="PsychoPy Error", style=wx.OK | wx.ICON_ERROR, pos=wx.DefaultPosition) errDlg.ShowModal() errDlg.Destroy() # since were not the main instance, exit ... self.quit(None) # ---- if showSplash: # show splash screen splashFile = os.path.join(self.prefs.paths['resources'], 'psychopySplash.png') splashImage = wx.Image(name=splashFile) splashImage.ConvertAlphaToMask() splash = AS.AdvancedSplash(None, bitmap=splashImage.ConvertToBitmap(), timeout=3000, agwStyle=AS.AS_TIMEOUT | AS.AS_CENTER_ON_SCREEN) w, h = splashImage.GetSize() splash.SetTextPosition((340, h - 30)) splash.SetText( _translate("Copyright (C) 2022 OpenScienceTools.org")) else: splash = None # SLOW IMPORTS - these need to be imported after splash screen starts # but then that they end up being local so keep track in self from psychopy.compatibility import checkCompatibility # import coder and builder here but only use them later from psychopy.app import coder, builder, runner, dialogs if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData: # must be before 1.74.00 last = self.prefs.appData['lastVersion'] = '1.73.04' self.firstRun = True else: last = self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: pass # setup links for URLs # on a mac, don't exit when the last frame is deleted, just show menu if sys.platform == 'darwin': self.menuFrame = MenuFrame(parent=None, app=self) # fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts = self.prefs.appData['coder']['prevFiles'] else: scripts = [] appKeys = list(self.prefs.appData['builder'].keys()) if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in appKeys): exps = self.prefs.appData['builder']['prevFiles'] else: exps = [] runlist = [] self.dpi = int(wx.GetDisplaySize()[0] / float(wx.GetDisplaySizeMM()[0]) * 25.4) # detect retina displays self.isRetina = self.dpi > 80 and wx.Platform == '__WXMAC__' if self.isRetina: fontScale = 1.2 # fonts are looking tiny on macos (only retina?) right now # mark icons as being retina icons.retStr = "@2x" else: fontScale = 1 # adjust dpi to something reasonable if not (50 < self.dpi < 120): self.dpi = 80 # dpi was unreasonable, make one up # Manage fonts if sys.platform == 'win32': # wx.SYS_DEFAULT_GUI_FONT is default GUI font in Win32 self._mainFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) else: self._mainFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) # rescale for tiny retina fonts if hasattr(wx.Font, "AddPrivateFont") and sys.platform != "darwin": # Load packaged fonts if possible for fontFile in (Path(__file__).parent / "Resources" / "fonts").glob("*"): if fontFile.suffix in ['.ttf', '.truetype']: wx.Font.AddPrivateFont(str(fontFile)) # Set fonts as those loaded self._codeFont = wx.Font( wx.FontInfo( self._mainFont.GetPointSize()).FaceName("JetBrains Mono")) else: # Get system defaults if can't load fonts try: self._codeFont = wx.SystemSettings.GetFont( wx.SYS_ANSI_FIXED_FONT) except wx._core.wxAssertionError: # if no SYS_ANSI_FIXED_FONT then try generic FONTFAMILY_MODERN self._codeFont = wx.Font(self._mainFont.GetPointSize(), wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) if self.isRetina: self._codeFont.SetPointSize( int(self._codeFont.GetPointSize() * fontScale)) self._mainFont.SetPointSize( int(self._mainFont.GetPointSize() * fontScale)) # that gets most of the properties of _codeFont but the FaceName # FaceName is set in the setting of the theme: self.theme = prefs.app['theme'] # removed Aug 2017: on newer versions of wx (at least on mac) # this looks too big # if hasattr(self._mainFont, 'Larger'): # # Font.Larger is available since wyPython version 2.9.1 # # PsychoPy still supports 2.8 (see ensureMinimal above) # self._mainFont = self._mainFont.Larger() # self._codeFont.SetPointSize( # self._mainFont.GetPointSize()) # unify font size # create both frame for coder/builder as necess if splash: splash.SetText(_translate(" Creating frames...")) # Parse incoming call parser = argparse.ArgumentParser(prog=self) parser.add_argument('--builder', dest='builder', action="store_true") parser.add_argument('-b', dest='builder', action="store_true") parser.add_argument('--coder', dest='coder', action="store_true") parser.add_argument('-c', dest='coder', action="store_true") parser.add_argument('--runner', dest='runner', action="store_true") parser.add_argument('-r', dest='runner', action="store_true") parser.add_argument('-x', dest='direct', action='store_true') view, args = parser.parse_known_args(sys.argv) # Check from filetype if any windows need to be open if any(arg.endswith('.psyexp') for arg in args): view.builder = True exps = [file for file in args if file.endswith('.psyexp')] if any(arg.endswith('.psyrun') for arg in args): view.runner = True runlist = [file for file in args if file.endswith('.psyrun')] # If still no window specified, use default from prefs if not any( getattr(view, key) for key in ['builder', 'coder', 'runner']): if self.prefs.app['defaultView'] in view: setattr(view, self.prefs.app['defaultView'], True) elif self.prefs.app['defaultView'] == 'all': view.builder = True view.coder = True view.runner = True # set the dispatcher for standard output # self.stdStreamDispatcher = console.StdStreamDispatcher(self) # self.stdStreamDispatcher.redirect() # Create windows if view.runner: self.showRunner(fileList=runlist) if view.coder: self.showCoder(fileList=scripts) if view.builder: self.showBuilder(fileList=exps) if view.direct: self.showRunner() for exp in [ file for file in args if file.endswith('.psyexp') or file.endswith('.py') ]: self.runner.panel.runFile(exp) # send anonymous info to www.psychopy.org/usage.php # please don't disable this, it's important for PsychoPy's development self._latestAvailableVersion = None self.updater = None self.news = None self.tasks = None prefsConn = self.prefs.connections ok, msg = checkCompatibility(last, self.version, self.prefs, fix=True) # tell the user what has changed if not ok and not self.firstRun and not self.testMode: title = _translate("Compatibility information") dlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title=title) dlg.ShowModal() if self.prefs.app['showStartupTips'] and not self.testMode: tipFile = os.path.join(self.prefs.paths['resources'], _translate("tips.txt")) tipIndex = self.prefs.appData['tipIndex'] if parse_version(wx.__version__) >= parse_version('4.0.0a1'): tp = wx.adv.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.adv.ShowTip(None, tp) else: tp = wx.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() self.Bind(wx.EVT_IDLE, self.onIdle) # doing this once subsequently enables the app to open & switch among # wx-windows on some platforms (Mac 10.9.4) with wx-3.0: v = parse_version if sys.platform == 'darwin': if v('3.0') <= v(wx.version()) < v('4.0'): _Showgui_Hack() # returns ~immediately, no display # focus stays in never-land, so bring back to the app: if prefs.app['defaultView'] in [ 'all', 'builder', 'coder', 'runner' ]: self.showBuilder() else: self.showCoder() # after all windows are created (so errors flushed) create output self._appLoaded = True if self.coder: self.coder.setOutputWindow() # takes control of sys.stdout # flush any errors to the last run log file logging.flush() sys.stdout.flush() # we wanted debug mode while loading but safe to go back to info mode if not self.prefs.app['debugMode']: logging.console.setLevel(logging.INFO) # if the program gets here, there are no other instances running self._timer = wx.PyTimer(self._bgCheckAndLoad) self._timer.Start(250) return True
def onInit(self, showSplash=True, testMode=False): """This is launched immediately *after* the app initialises with wx :Parameters: testMode: bool """ self.SetAppName('PsychoPy3') if showSplash: #showSplash: # show splash screen splashFile = os.path.join(self.prefs.paths['resources'], 'psychopySplash.png') splashImage = wx.Image(name=splashFile) splashImage.ConvertAlphaToMask() splash = AS.AdvancedSplash( None, bitmap=splashImage.ConvertToBitmap(), timeout=3000, agwStyle=AS.AS_TIMEOUT | AS.AS_CENTER_ON_SCREEN, ) # transparency? w, h = splashImage.GetSize() splash.SetTextPosition((int(340), h - 30)) splash.SetText( _translate("Copyright (C) 2020 OpenScienceTools.org")) else: splash = None # SLOW IMPORTS - these need to be imported after splash screen starts # but then that they end up being local so keep track in self from psychopy.compatibility import checkCompatibility # import coder and builder here but only use them later from psychopy.app import coder, builder, runner, dialogs if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData: # must be before 1.74.00 last = self.prefs.appData['lastVersion'] = '1.73.04' self.firstRun = True else: last = self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: pass # setup links for URLs # on a mac, don't exit when the last frame is deleted, just show menu if sys.platform == 'darwin': self.menuFrame = MenuFrame(parent=None, app=self) # fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts = self.prefs.appData['coder']['prevFiles'] else: scripts = [] appKeys = list(self.prefs.appData['builder'].keys()) if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in appKeys): exps = self.prefs.appData['builder']['prevFiles'] else: exps = [] runlist = [] self.dpi = int(wx.GetDisplaySize()[0] / float(wx.GetDisplaySizeMM()[0]) * 25.4) if not (50 < self.dpi < 120): self.dpi = 80 # dpi was unreasonable, make one up if sys.platform == 'win32': # wx.SYS_DEFAULT_GUI_FONT is default GUI font in Win32 self._mainFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) else: self._mainFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) try: self._codeFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) except wx._core.wxAssertionError: # if no SYS_ANSI_FIXED_FONT then try generic FONTFAMILY_MODERN self._codeFont = wx.Font(self._mainFont.GetPointSize(), wx.FONTFAMILY_MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) # that gets most of the properties of _codeFont but the FaceName # FaceName is set in the setting of the theme: self.theme = self.prefs.app['theme'] # removed Aug 2017: on newer versions of wx (at least on mac) # this looks too big # if hasattr(self._mainFont, 'Larger'): # # Font.Larger is available since wyPython version 2.9.1 # # PsychoPy still supports 2.8 (see ensureMinimal above) # self._mainFont = self._mainFont.Larger() # self._codeFont.SetPointSize( # self._mainFont.GetPointSize()) # unify font size # create both frame for coder/builder as necess if splash: splash.SetText(_translate(" Creating frames...")) # Parse incoming call parser = argparse.ArgumentParser(prog=self) parser.add_argument('--builder', dest='builder', action="store_true") parser.add_argument('-b', dest='builder', action="store_true") parser.add_argument('--coder', dest='coder', action="store_true") parser.add_argument('-c', dest='coder', action="store_true") parser.add_argument('--runner', dest='runner', action="store_true") parser.add_argument('-r', dest='runner', action="store_true") view, args = parser.parse_known_args(sys.argv) print(args) # Check from filetype if any windows need to be open if any(arg.endswith('.psyexp') for arg in args): view.builder = True exps = [file for file in args if file.endswith('.psyexp')] if any(arg.endswith('.psyrun') for arg in args): view.runner = True runlist = [file for file in args if file.endswith('.psyrun')] # If still no window specified, use default from prefs if not any( getattr(view, key) for key in ['builder', 'coder', 'runner']): if self.prefs.app['defaultView'] in view: setattr(view, self.prefs.app['defaultView'], True) elif self.prefs.app['defaultView'] == 'all': view.builder = True view.coder = True view.runner = True # Create windows if view.runner: self.showRunner(fileList=runlist) if view.coder: self.showCoder(fileList=scripts) if view.builder: self.showBuilder(fileList=exps) # if darwin, check for inaccessible keyboard if sys.platform == 'darwin': from psychopy.hardware import keyboard if keyboard.macPrefsBad: title = _translate("Mac keyboard security") if platform.mac_ver()[0] < '10.15': settingName = 'Accessibility' setting = 'Privacy_Accessibility' else: setting = 'Privacy_ListenEvent' settingName = 'Input Monitoring' msg = _translate( "To use high-precision keyboard timing you should " "enable {} for PsychoPy in System Preferences. " "Shall we go there (and you can drag PsychoPy app into " "the box)?").format(settingName) dlg = dialogs.MessageDialog(title=title, message=msg, type='Query') resp = dlg.ShowModal() if resp == wx.ID_YES: from AppKit import NSWorkspace from Foundation import NSURL sys_pref_link = ('x-apple.systempreferences:' 'com.apple.preference.security?' '{}'.format(setting)) # create workspace object workspace = NSWorkspace.sharedWorkspace() # Open System Preference workspace.openURL_(NSURL.URLWithString_(sys_pref_link)) # send anonymous info to www.psychopy.org/usage.php # please don't disable this, it's important for PsychoPy's development self._latestAvailableVersion = None self.updater = None self.news = None self.tasks = None prefsConn = self.prefs.connections ok, msg = checkCompatibility(last, self.version, self.prefs, fix=True) # tell the user what has changed if not ok and not self.firstRun and not self.testMode: title = _translate("Compatibility information") dlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title=title) dlg.ShowModal() if (self.prefs.app['showStartupTips'] and not self.testMode and not blockTips): tipFile = os.path.join(self.prefs.paths['resources'], _translate("tips.txt")) tipIndex = self.prefs.appData['tipIndex'] if parse_version(wx.__version__) >= parse_version('4.0.0a1'): tp = wx.adv.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.adv.ShowTip(None, tp) else: tp = wx.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() self.Bind(wx.EVT_IDLE, self.onIdle) # doing this once subsequently enables the app to open & switch among # wx-windows on some platforms (Mac 10.9.4) with wx-3.0: v = parse_version if sys.platform == 'darwin': if v('3.0') <= v(wx.version()) < v('4.0'): _Showgui_Hack() # returns ~immediately, no display # focus stays in never-land, so bring back to the app: if prefs.app['defaultView'] in [ 'all', 'builder', 'coder', 'runner' ]: self.showBuilder() else: self.showCoder() # after all windows are created (so errors flushed) create output self._appLoaded = True if self.coder: self.coder.setOutputWindow() # takes control of sys.stdout # flush any errors to the last run log file logging.flush() sys.stdout.flush() # we wanted debug mode while loading but safe to go back to info mode if not self.prefs.app['debugMode']: logging.console.setLevel(logging.INFO) # Runner captures standard streams until program closed if self.runner and not self.testMode: sys.stdout = self.runner.stdOut sys.stderr = self.runner.stdOut return True
def onInit(self, showSplash=True, testMode=False): """This is launched immediately *after* the app initialises with wx :Parameters: testMode: bool """ self.SetAppName('PsychoPy3') if False: # show splash screen splashFile = os.path.join(self.prefs.paths['resources'], 'psychopySplash.png') splashImage = wx.Image(name=splashFile) splashImage.ConvertAlphaToMask() splash = AS.AdvancedSplash( None, bitmap=splashImage.ConvertToBitmap(), timeout=3000, agwStyle=AS.AS_TIMEOUT | AS.AS_CENTER_ON_SCREEN, ) # transparency? w, h = splashImage.GetSize() splash.SetTextPosition((int(w - 130), h - 20)) splash.SetText(_translate("Loading libraries...")) wx.Yield() else: splash = None # SLOW IMPORTS - these need to be imported after splash screen starts # but then that they end up being local so keep track in self if splash: splash.SetText(_translate("Loading PsychoPy3...")) wx.Yield() from psychopy.compatibility import checkCompatibility # import coder and builder here but only use them later from psychopy.app import coder, builder, dialogs if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData: # must be before 1.74.00 last = self.prefs.appData['lastVersion'] = '1.73.04' self.firstRun = True else: last = self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: pass # setup links for URLs # on a mac, don't exit when the last frame is deleted, just show menu if sys.platform == 'darwin': self.menuFrame = MenuFrame(parent=None, app=self) # get preferred view(s) from prefs and previous view if self.prefs.app['defaultView'] == 'last': mainFrame = self.prefs.appData['lastFrame'] else: # configobjValidate should take care of this situation allowed = ['last', 'coder', 'builder', 'both'] if self.prefs.app['defaultView'] in allowed: mainFrame = self.prefs.app['defaultView'] else: self.prefs.app['defaultView'] = 'both' mainFrame = 'both' # fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts = self.prefs.appData['coder']['prevFiles'] else: scripts = [] appKeys = list(self.prefs.appData['builder'].keys()) if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in appKeys): exps = self.prefs.appData['builder']['prevFiles'] else: exps = [] # then override the prev files by command options and passed files if len(sys.argv) > 1: if sys.argv[1] == __name__: # program was executed as "python.exe psychopyApp.py %1' args = sys.argv[2:] else: # program was executed as "psychopyApp.py %1' args = sys.argv[1:] # choose which frame to start with if args[0] in ['builder', '--builder', '-b']: mainFrame = 'builder' args = args[1:] # can remove that argument elif args[0] in ['coder', '--coder', '-c']: mainFrame = 'coder' args = args[1:] # can remove that argument # did we get .py or .psyexp files? elif args[0][-7:] == '.psyexp': mainFrame = 'builder' exps = [args[0]] elif args[0][-3:] == '.py': mainFrame = 'coder' scripts = [args[0]] else: args = [] self.dpi = int(wx.GetDisplaySize()[0] / float(wx.GetDisplaySizeMM()[0]) * 25.4) if not (50 < self.dpi < 120): self.dpi = 80 # dpi was unreasonable, make one up if sys.platform == 'win32': # wx.SYS_DEFAULT_GUI_FONT is default GUI font in Win32 self._mainFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) else: self._mainFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) self._codeFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) self._codeFont.SetFaceName(self.prefs.coder['codeFont']) # removed Aug 2017: on newer versions of wx (at least on mac) # this looks too big # if hasattr(self._mainFont, 'Larger'): # # Font.Larger is available since wyPython version 2.9.1 # # PsychoPy still supports 2.8 (see ensureMinimal above) # self._mainFont = self._mainFont.Larger() # self._codeFont.SetPointSize( # self._mainFont.GetPointSize()) # unify font size # create both frame for coder/builder as necess if splash: splash.SetText(_translate(" Creating frames...")) if mainFrame in ['both', 'coder']: self.showCoder(fileList=scripts) if mainFrame in ['both', 'builder']: self.showBuilder(fileList=exps) # send anonymous info to www.psychopy.org/usage.php # please don't disable this, it's important for PsychoPy's development self._latestAvailableVersion = None self.updater = None prefsConn = self.prefs.connections if prefsConn['checkForUpdates'] or prefsConn['allowUsageStats']: connectThread = threading.Thread( target=connections.makeConnections, args=(self, )) connectThread.start() # query github in the background to populate a local cache about # what versions are available for download: from psychopy.tools import versionchooser as vc versionsThread = threading.Thread(target=vc._remoteVersions, args=(True, )) versionsThread.start() try: import imageio haveImageio = True except ImportError: haveImageio = False if haveImageio: # Use pre-installed ffmpeg if available. # Otherwise, download ffmpeg binary. try: imageio.plugins.ffmpeg.get_exe() except imageio.core.NeedDownloadError: ffmpegDownloader = threading.Thread( target=imageio.plugins.ffmpeg.download) ffmpegDownloader.start() ok, msg = checkCompatibility(last, self.version, self.prefs, fix=True) # tell the user what has changed if not ok and not self.firstRun and not self.testMode: title = _translate("Compatibility information") dlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title=title) dlg.ShowModal() if self.prefs.app['showStartupTips'] and not self.testMode: tipFile = os.path.join(self.prefs.paths['resources'], _translate("tips.txt")) tipIndex = self.prefs.appData['tipIndex'] if parse_version(wx.__version__) >= parse_version('4.0.0a1'): tp = wx.adv.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.adv.ShowTip(None, tp) else: tp = wx.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() if self.prefs.connections['checkForUpdates']: self.Bind(wx.EVT_IDLE, self.checkUpdates) else: self.Bind(wx.EVT_IDLE, self.onIdle) # doing this once subsequently enables the app to open & switch among # wx-windows on some platforms (Mac 10.9.4) with wx-3.0: v = parse_version if sys.platform == 'darwin': if v('3.0') <= v(wx.version()) < v('4.0'): _Showgui_Hack() # returns ~immediately, no display # focus stays in never-land, so bring back to the app: if mainFrame in ['both', 'builder']: self.showBuilder() else: self.showCoder() # after all windows are created (so errors flushed) create output self._appLoaded = True if self.coder: self.coder.setOutputWindow() # takes control of sys.stdout return True
def onInit(self, showSplash=True, testMode=False): """This is launched immediately *after* the app initialises with wx :Parameters: testMode: bool """ self.SetAppName('PsychoPy3') if showSplash: #showSplash: # show splash screen splashFile = os.path.join(self.prefs.paths['resources'], 'psychopySplash.png') splashImage = wx.Image(name=splashFile) splashImage.ConvertAlphaToMask() splash = AS.AdvancedSplash( None, bitmap=splashImage.ConvertToBitmap(), timeout=3000, agwStyle=AS.AS_TIMEOUT | AS.AS_CENTER_ON_SCREEN, ) # transparency? w, h = splashImage.GetSize() splash.SetTextPosition((int(340), h - 30)) splash.SetText( _translate("Copyright (C) 2021 OpenScienceTools.org")) else: splash = None # SLOW IMPORTS - these need to be imported after splash screen starts # but then that they end up being local so keep track in self from psychopy.compatibility import checkCompatibility # import coder and builder here but only use them later from psychopy.app import coder, builder, runner, dialogs if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData: # must be before 1.74.00 last = self.prefs.appData['lastVersion'] = '1.73.04' self.firstRun = True else: last = self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: pass # setup links for URLs # on a mac, don't exit when the last frame is deleted, just show menu if sys.platform == 'darwin': self.menuFrame = MenuFrame(parent=None, app=self) # fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts = self.prefs.appData['coder']['prevFiles'] else: scripts = [] appKeys = list(self.prefs.appData['builder'].keys()) if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in appKeys): exps = self.prefs.appData['builder']['prevFiles'] else: exps = [] runlist = [] self.dpi = int(wx.GetDisplaySize()[0] / float(wx.GetDisplaySizeMM()[0]) * 25.4) # detect retina displays self.isRetina = self.dpi > 80 and wx.Platform == '__WXMAC__' if self.isRetina: fontScale = 1.2 # fonts are looking tiny on macos (only retina?) right now else: fontScale = 1 # adjust dpi to something reasonable if not (50 < self.dpi < 120): self.dpi = 80 # dpi was unreasonable, make one up # Manage fonts if sys.platform == 'win32': # wx.SYS_DEFAULT_GUI_FONT is default GUI font in Win32 self._mainFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) else: self._mainFont = wx.SystemSettings.GetFont(wx.SYS_ANSI_FIXED_FONT) # rescale for tiny retina fonts if hasattr(wx.Font, "AddPrivateFont") and sys.platform != "darwin": # Load packaged fonts if possible for fontFile in (Path(__file__).parent / "Resources" / "fonts").glob("*"): if fontFile.suffix in ['.ttf', '.truetype']: wx.Font.AddPrivateFont(str(fontFile)) # Set fonts as those loaded self._codeFont = wx.Font( wx.FontInfo( self._mainFont.GetPointSize()).FaceName("JetBrains Mono")) else: # Get system defaults if can't load fonts try: self._codeFont = wx.SystemSettings.GetFont( wx.SYS_ANSI_FIXED_FONT) except wx._core.wxAssertionError: # if no SYS_ANSI_FIXED_FONT then try generic FONTFAMILY_MODERN self._codeFont = wx.Font(self._mainFont.GetPointSize(), wx.FONTFAMILY_TELETYPE, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) if self.isRetina: self._codeFont.SetPointSize( int(self._codeFont.GetPointSize() * fontScale)) self._mainFont.SetPointSize( int(self._mainFont.GetPointSize() * fontScale)) # that gets most of the properties of _codeFont but the FaceName # FaceName is set in the setting of the theme: self.theme = self.prefs.app['theme'] # removed Aug 2017: on newer versions of wx (at least on mac) # this looks too big # if hasattr(self._mainFont, 'Larger'): # # Font.Larger is available since wyPython version 2.9.1 # # PsychoPy still supports 2.8 (see ensureMinimal above) # self._mainFont = self._mainFont.Larger() # self._codeFont.SetPointSize( # self._mainFont.GetPointSize()) # unify font size # create both frame for coder/builder as necess if splash: splash.SetText(_translate(" Creating frames...")) # Parse incoming call parser = argparse.ArgumentParser(prog=self) parser.add_argument('--builder', dest='builder', action="store_true") parser.add_argument('-b', dest='builder', action="store_true") parser.add_argument('--coder', dest='coder', action="store_true") parser.add_argument('-c', dest='coder', action="store_true") parser.add_argument('--runner', dest='runner', action="store_true") parser.add_argument('-r', dest='runner', action="store_true") parser.add_argument('-x', dest='direct', action='store_true') view, args = parser.parse_known_args(sys.argv) # Check from filetype if any windows need to be open if any(arg.endswith('.psyexp') for arg in args): view.builder = True exps = [file for file in args if file.endswith('.psyexp')] if any(arg.endswith('.psyrun') for arg in args): view.runner = True runlist = [file for file in args if file.endswith('.psyrun')] # If still no window specified, use default from prefs if not any( getattr(view, key) for key in ['builder', 'coder', 'runner']): if self.prefs.app['defaultView'] in view: setattr(view, self.prefs.app['defaultView'], True) elif self.prefs.app['defaultView'] == 'all': view.builder = True view.coder = True view.runner = True # set the dispatcher for standard output self.stdStreamDispatcher = console.StdStreamDispatcher(self) self.stdStreamDispatcher.redirect() # Create windows if view.runner: self.showRunner(fileList=runlist) if view.coder: self.showCoder(fileList=scripts) if view.builder: self.showBuilder(fileList=exps) if view.direct: self.showRunner() for exp in [ file for file in args if file.endswith('.psyexp') or file.endswith('.py') ]: self.runner.panel.runFile(exp) # send anonymous info to www.psychopy.org/usage.php # please don't disable this, it's important for PsychoPy's development self._latestAvailableVersion = None self.updater = None self.news = None self.tasks = None prefsConn = self.prefs.connections ok, msg = checkCompatibility(last, self.version, self.prefs, fix=True) # tell the user what has changed if not ok and not self.firstRun and not self.testMode: title = _translate("Compatibility information") dlg = dialogs.MessageDialog(parent=None, message=msg, type='Info', title=title) dlg.ShowModal() if (self.prefs.app['showStartupTips'] and not self.testMode and not blockTips): tipFile = os.path.join(self.prefs.paths['resources'], _translate("tips.txt")) tipIndex = self.prefs.appData['tipIndex'] if parse_version(wx.__version__) >= parse_version('4.0.0a1'): tp = wx.adv.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.adv.ShowTip(None, tp) else: tp = wx.CreateFileTipProvider(tipFile, tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() self.Bind(wx.EVT_IDLE, self.onIdle) # doing this once subsequently enables the app to open & switch among # wx-windows on some platforms (Mac 10.9.4) with wx-3.0: v = parse_version if sys.platform == 'darwin': if v('3.0') <= v(wx.version()) < v('4.0'): _Showgui_Hack() # returns ~immediately, no display # focus stays in never-land, so bring back to the app: if prefs.app['defaultView'] in [ 'all', 'builder', 'coder', 'runner' ]: self.showBuilder() else: self.showCoder() # after all windows are created (so errors flushed) create output self._appLoaded = True if self.coder: self.coder.setOutputWindow() # takes control of sys.stdout # flush any errors to the last run log file logging.flush() sys.stdout.flush() # we wanted debug mode while loading but safe to go back to info mode if not self.prefs.app['debugMode']: logging.console.setLevel(logging.INFO) return True
def onInit(self, showSplash=True, testMode=False): """ :Parameters: testMode: bool If set to True then startup wizard won't appear and stdout/stderr won't be redirected to the Coder """ self.version=psychopy.__version__ self.SetAppName('PsychoPy2') #set default paths and prefs self.prefs = psychopy.prefs if self.prefs.app['debugMode']: logging.console.setLevel(logging.DEBUG) self.testMode = testMode #indicates whether we're running for testing purposes if showSplash: #show splash screen splashFile = os.path.join(self.prefs.paths['resources'], 'psychopySplash.png') splashBitmap = wx.Image(name = splashFile).ConvertToBitmap() splash = AS.AdvancedSplash(None, bitmap=splashBitmap, timeout=3000, style=AS.AS_TIMEOUT|wx.FRAME_SHAPED, shadowcolour=wx.RED)#could use this in future for transparency splash.SetTextPosition((10,240)) splash.SetText(" Loading libraries...") else: splash=None #LONG IMPORTS - these need to be imported after splash screen starts (they're slow) #but then that they end up being local so keep track in self if splash: splash.SetText(" Loading PsychoPy2...") from psychopy import compatibility from psychopy.app import coder, builder, dialogs, wxIDs, urls #import coder and builder here but only use them later self.keys = self.prefs.keys self.prefs.pageCurrent = 0 # track last-viewed page of prefs, to return there self.IDs=wxIDs self.urls=urls.urls self.quitting=False #check compatibility with last run version (before opening windows) self.firstRun = False if '--firstrun' in sys.argv: del sys.argv[sys.argv.index('--firstrun')] self.firstRun = True if 'lastVersion' not in self.prefs.appData.keys(): last=self.prefs.appData['lastVersion']='1.73.04'#must be before 1.74.00 self.firstRun = True else: last=self.prefs.appData['lastVersion'] if self.firstRun and not self.testMode: self.firstrunWizard() #setup links for URLs #on a mac, don't exit when the last frame is deleted, just show a menu if sys.platform=='darwin': self.menuFrame=MenuFrame(parent=None, app=self) #get preferred view(s) from prefs and previous view if self.prefs.app['defaultView']=='last': mainFrame = self.prefs.appData['lastFrame'] else: # configobjValidate should take care of this situation (?), but doesn't: if self.prefs.app['defaultView'] in ['last', 'coder', 'builder', 'both']: mainFrame = self.prefs.app['defaultView'] else: self.prefs.app['defaultView'] = 'both' mainFrame = 'both' #fetch prev files if that's the preference if self.prefs.coder['reloadPrevFiles']: scripts=self.prefs.appData['coder']['prevFiles'] else: scripts=[] if self.prefs.builder['reloadPrevExp'] and ('prevFiles' in self.prefs.appData['builder'].keys()): exps=self.prefs.appData['builder']['prevFiles'] else: exps=[] #then override the prev files by command options and passed files if len(sys.argv)>1: if sys.argv[1]==__name__: args = sys.argv[2:] # program was executed as "python.exe PsychoPyIDE.py %1' else: args = sys.argv[1:] # program was executed as "PsychoPyIDE.py %1' #choose which frame to start with if args[0] in ['builder', '--builder', '-b']: mainFrame='builder' args = args[1:]#can remove that argument elif args[0] in ['coder','--coder', '-c']: mainFrame='coder' args = args[1:]#can remove that argument #did we get .py or .psyexp files? elif args[0][-7:]=='.psyexp': mainFrame='builder' exps=[args[0]] elif args[0][-3:]=='.py': mainFrame='coder' scripts=[args[0]] else: args=[] self.dpi = int(wx.GetDisplaySize()[0]/float(wx.GetDisplaySizeMM()[0])*25.4) if not (50<self.dpi<120): self.dpi=80#dpi was unreasonable, make one up #create both frame for coder/builder as necess if splash: splash.SetText(" Creating frames...") self.coder = None self.builderFrames = [] self.copiedRoutine=None self.allFrames=[]#these are ordered and the order is updated with self.onNewTopWindow if mainFrame in ['both', 'coder']: self.showCoder(fileList=scripts) if mainFrame in ['both', 'builder']: self.showBuilder(fileList=exps) #send anonymous info to www.psychopy.org/usage.php #please don't disable this - it's important for PsychoPy's development self._latestAvailableVersion=None self.updater=None if self.prefs.connections['checkForUpdates'] or self.prefs.connections['allowUsageStats']: connectThread = threading.Thread(target=connections.makeConnections, args=(self,)) connectThread.start() ok, msg = compatibility.checkCompatibility(last, self.version, self.prefs, fix=True) if not ok and not self.firstRun and not self.testMode: #tell the user what has changed dlg = dialogs.MessageDialog(parent=None,message=msg,type='Info', title="Compatibility information") dlg.ShowModal() if self.prefs.app['showStartupTips'] and not self.testMode: tipIndex = self.prefs.appData['tipIndex'] tp = wx.CreateFileTipProvider(os.path.join(self.prefs.paths['resources'],"tips.txt"), tipIndex) showTip = wx.ShowTip(None, tp) self.prefs.appData['tipIndex'] = tp.GetCurrentTip() self.prefs.saveAppData() self.prefs.app['showStartupTips'] = showTip self.prefs.saveUserPrefs() if self.prefs.connections['checkForUpdates']: self.Bind(wx.EVT_IDLE, self.checkUpdates) else: self.Bind(wx.EVT_IDLE, self.onIdle) return True