def set_rect(self, rect): """ desc: Sets the widget geometry. arguments: rect: desc: A (left, top, width, height) tuple. type: tuple """ self.rect = rect _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.isfile(_path): raise osexception(u'"%s" does not exist' % _path) if self.adjust: x, y, w, h = self.rect try: img = Image.open(_path) img_w, img_h = img.size except: try: import pygame img = pygame.image.load(_path) except: raise osexception( u'Failed to open image "%s". Perhaps the file is not an image, or the image format is not supported.' % self.path) img_w, img_h = img.get_size() scale_x = 1. * w / img_w scale_y = 1. * h / img_h self.scale = min(scale_x, scale_y) else: self.scale = 1 Widget.set_rect(self, rect)
def image(self, fname, center=True, x=None, y=None, scale=None): _fname = safe_str(fname, enc=misc.filesystem_encoding()) if not os.path.isfile(_fname): raise osexception(u'"%s" does not exist' % fname) try: surface = pygame.image.load(_fname) except pygame.error: raise osexception(u"'%s' is not a supported image format" % fname) if scale is not None: try: surface = pygame.transform.smoothscale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale)) ) except: debug.msg(u"smooth scaling failed for '%s'" % fname, reason=u"warning") surface = pygame.transform.scale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale)) ) size = surface.get_size() x, y = self.to_xy(x, y) if center: x -= size[0] / 2 y -= size[1] / 2 self.surface.blit(surface, (x, y))
def __init__(self, experiment, folder=None): """ visible: False desc: Constructor. arguments: experiment: desc: The experiment object. type: experiment keywords: folder: desc: The folder to use for the file pool, or `None` to create a new temporary folder. type: [str, unicode, NoneType] """ self.experiment = experiment if folder is None: # On some systems tempfile.mkdtemp() triggers a UnicodeDecodeError. # This is resolved by passing the dir explicitly as a Unicode # string. This fix has been adapted from: # - <http://bugs.python.org/issue1681974> self.__folder__ = tempfile.mkdtemp(suffix=u'.opensesame_pool', dir=safe_decode(tempfile.gettempdir(), enc=misc.filesystem_encoding())) debug.msg(u'creating new pool folder') else: debug.msg(u'reusing existing pool folder') self.__folder__ = folder debug.msg(u'pool folder is \'%s\'' % self.__folder__)
def __init__(self, plugin_file=None): """ Constructor. Arguments: plugin_file -- The path to the plugin script. (default=None) """ if plugin_file != None: # The __file__ variable is generally a str, which will cause unicode # errors. Therefore, convert this here if necessary. if isinstance(plugin_file, str): plugin_file = plugin_file.decode(misc.filesystem_encoding()) # These lines makes sure that the icons and help file are recognized # by OpenSesame. self.plugin_folder = os.path.dirname(plugin_file) self.experiment.resources[u'%s.png' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.png' % self.item_type) self.experiment.resources[u'%s_large.png' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s_large.png' \ % self.item_type) self.experiment.resources[u'%s.html' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.html' \ % self.item_type) self.experiment.resources[u'%s.md' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.md' \ % self.item_type) self.lock = False qtitem.qtitem.__init__(self)
def set_rect(self, rect): """ desc: Sets the widget geometry. arguments: rect: desc: A (left, top, width, height) tuple. type: tuple """ self.rect = rect _path = safe_str(self.path, enc=misc.filesystem_encoding()) if self.adjust: x, y, w, h = self.rect try: img = Image.open(_path) img_w, img_h = img.size except: try: import pygame img = pygame.image.load(_path) except: raise osexception( u'Failed to open image "%s". Perhaps the file is not an image, or the image format is not supported.' \ % self.path) img_w, img_h = img.get_size() scale_x = 1.*w/img_w scale_y = 1.*h/img_h self.scale = min(scale_x, scale_y) else: self.scale = 1
def __getitem__(self, path): """ visible: False desc: | Returns the full path to a file. arguments: path: desc: A filename. This can be any type, but will be coerced to `unicode` if it is not `unicode`. returns: desc: The full path to the file. type: unicode """ path = safe_decode(path) if path.strip() == u'': raise osexception(u'Cannot get empty filename from file pool.') for folder in self.folders(include_experiment_path=True): _path = os.path.normpath(os.path.join(folder, path)) if os.path.exists(safe_str(_path, enc=misc.filesystem_encoding())): return _path return os.path.normpath(path)
def image(self, fname, center=True, x=None, y=None, scale=None): _fname = safe_str(fname, enc=misc.filesystem_encoding()) if not os.path.isfile(_fname): raise osexception(u'"%s" does not exist' % fname) try: surface = pygame.image.load(_fname) except pygame.error: raise osexception(u"'%s' is not a supported image format" % fname) if scale is not None: try: surface = pygame.transform.smoothscale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale))) except: debug.msg(u"smooth scaling failed for '%s'" % fname, reason=u"warning") surface = pygame.transform.scale( surface, (int(surface.get_width() * scale), int(surface.get_height() * scale))) size = surface.get_size() x, y = self.to_xy(x, y) if center: x -= size[0] / 2 y -= size[1] / 2 self.surface.blit(surface, (x, y))
def image(self, fname, center=True, x=None, y=None, scale=None): # If the filename is a str, we first decode it to unicode if isinstance(fname, str): _fname = fname.decode(self.experiment.encoding) # Next, we encode the filename to a str in the filesystem encoding _fname = fname.encode(misc.filesystem_encoding()) try: surface = pygame.image.load(_fname) except pygame.error as e: raise osexception( u"'%s' is not a supported image format" % fname) if scale != None: try: surface = pygame.transform.smoothscale(surface, (int(surface.get_width()*scale), int(surface.get_height()*scale))) except: debug.msg(u"smooth scaling failed for '%s'" % fname, reason=u"warning") surface = pygame.transform.scale(surface, (int(surface.get_width()*scale), int(surface.get_height()*scale))) size = surface.get_size() if x == None: x = self.xcenter() if y == None: y = self.ycenter() if center: x -= size[0] / 2 y -= size[1] / 2 self.surface.blit(surface, (x, y))
def _read_tarfile(self, format): """ visible: False desc: Reads a tar or targz archive. arguments: format: desc: The format to be used for tarfile.open(). type: str """ self._experiment_path = os.path.dirname(self._src) tar = tarfile.open(self._src, format) for name in tar.getnames(): # Tar doesn't return unicode in Python 2 uname = safe_decode(name) folder, fname = os.path.split(uname) # Ignore everything except the pool folder if folder != u'pool': continue # Filenames are encoded with U+XXXX notation in the archive. This is # necessary to deal with absence of good unicode support in .tar.gz. fname = self._syntax.from_ascii(fname) pool_folder = safe_str(self._pool.folder(), enc=misc.filesystem_encoding()) from_name = safe_str(os.path.join(self._pool.folder(), uname), enc=misc.filesystem_encoding()) to_name = safe_str(os.path.join(self._pool.folder(), fname), enc=misc.filesystem_encoding()) tar.extract(name, pool_folder) os.rename(from_name, to_name) os.rmdir(os.path.join(self._pool.folder(), folder)) # Temporarily extract the script file to the file pool, and remove it # right away script_path = os.path.join(self._pool.folder(), u'script.opensesame') tar.extract(u'script.opensesame', self._pool.folder()) with safe_open(script_path, universal_newline_mode) as fd: self._script = fd.read() os.remove(script_path)
def open(self, src): """ If the path exists, open the file, extract the pool and return the contents of the script.opensesame. Otherwise just return the input string, because it probably was a definition to begin with. Arguments: src -- A definition string or a file to be opened. Returns: A unicode defition string. """ # If the path is not a path at all, but a string containing # the script, return it. Also, convert the path back to Unicode before # returning. if not os.path.exists(src): debug.msg(u'opening from unicode string') self.experiment_path = None if isinstance(src, unicode): return src return src.decode(self.encoding, u'replace') # If the file is a regular text script, # read it and return it ext = u'.opensesame.tar.gz' if src[-len(ext):] != ext: debug.msg(u'opening .opensesame file') self.experiment_path = os.path.dirname(src) return self.unsanitize(open(src, u'rU').read()) debug.msg(u"opening .opensesame.tar.gz file") # If the file is a .tar.gz archive, extract the pool to the pool folder # and return the contents of opensesame.script. tar = tarfile.open(src, u'r:gz') for name in tar.getnames(): # Here, all paths except name are Unicode. In addition, fname is # Unicode unsanitized, because the files as saved are Unicode # sanitized (see save()). uname = name.decode(self.encoding) folder, fname = os.path.split(uname) fname = self.unsanitize(fname) if folder == u"pool": debug.msg(u"extracting '%s'" % uname) tar.extract(name, self.pool_folder.encode( \ misc.filesystem_encoding())) os.rename(os.path.join(self.pool_folder, uname), \ os.path.join(self.pool_folder, fname)) os.rmdir(os.path.join(self.pool_folder, folder)) script_path = os.path.join(self.pool_folder, u"script.opensesame") tar.extract(u"script.opensesame", self.pool_folder) script = self.unsanitize(open(script_path, u"rU").read()) os.remove(script_path) self.experiment_path = os.path.dirname(src) return script
def import_plugin(plugin): """ Imports plugin module Arguments: plugin -- the name of the plugin """ import imp plugin = str(plugin) for tmpl in src_templates: if os.path.exists(os.path.join(plugin_folder(plugin), tmpl % plugin)): path = os.path.join(plugin_folder(plugin), tmpl % plugin).encode( \ misc.filesystem_encoding()) return imp.load_source(plugin, path) for tmpl in bytecode_templates: if os.path.exists(os.path.join(plugin_folder(plugin), tmpl % plugin)): path = os.path.join(plugin_folder(plugin), tmpl % plugin).encode( \ misc.filesystem_encoding()) return imp.load_compiled(plugin, path)
def plugin_folders(only_existing=True, _type=u'plugins'): """ desc: Returns a list of plugin folders. keywords: only_existing: desc: Specifies if only existing folders should be returned. type: bool _type: desc: Indicates whether runtime plugins ('plugins') or GUI extensions ('extensions') should be listed. type: [str, unicode] returns: desc: A list of folders. type: list """ l = [] # For all platforms, the plugins folder relative to the working directory # should be searched path = os.path.join(os.getcwdu(), _type) if not only_existing or os.path.exists(path): l.append(path) if os.name == u'posix' and u'HOME' in os.environ: # Regular Linux distributions. TODO: How well does this apply to Mac OS? path = os.path.join(os.environ[u'HOME'], u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) path = u'/usr/share/opensesame/%s' % _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'posix' and u'HOME' not in os.environ: # Android can be recognized by the fact that the HOME variable is not # available. We can simply use the relative path `plugins`, which will # (always?) point to `/data/data/nl.cogsci.nl/opensesame/files/plugins` path = _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'nt': # Windows path = os.path.join( os.environ[u'APPDATA'].decode(misc.filesystem_encoding()), u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) return l
def plugin_folders(only_existing=True, _type=u'plugins'): """ desc: Returns a list of plugin folders. keywords: only_existing: desc: Specifies if only existing folders should be returned. type: bool _type: desc: Indicates whether runtime plugins ('plugins') or GUI extensions ('extensions') should be listed. type: [str, unicode] returns: desc: A list of folders. type: list """ l = [] # For all platforms, the plugins folder relative to the working directory # should be searched path = os.path.join(os.getcwdu(), _type) if not only_existing or os.path.exists(path): l.append(path) if os.name == u'posix' and u'HOME' in os.environ: # Regular Linux distributions. TODO: How well does this apply to Mac OS? path = os.path.join(os.environ[u'HOME'], u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) path = u'/usr/share/opensesame/%s' % _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'posix' and u'HOME' not in os.environ: # Android can be recognized by the fact that the HOME variable is not # available. We can simply use the relative path `plugins`, which will # (always?) point to `/data/data/nl.cogsci.nl/opensesame/files/plugins` path = _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'nt': # Windows path = os.path.join(os.environ[u'APPDATA'].decode( misc.filesystem_encoding()), u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) return l
def _init_pyqt(self, exp): global app, font_database # Add the Qt plugin folders to the library path, if they exists. Where # these folders are depends on the version of Qt4, but these are two # possible locations. qt_plugin_path = os.path.join(os.path.dirname(sys.executable), 'Library', 'plugins') if os.path.isdir(qt_plugin_path): QCoreApplication.addLibraryPath( safe_decode(qt_plugin_path, enc=misc.filesystem_encoding())) qt_plugin_path = os.path.join(os.path.dirname(sys.executable), 'Library', 'lib', 'qt4', 'plugins') if os.path.isdir(qt_plugin_path): QCoreApplication.addLibraryPath( safe_decode(qt_plugin_path, enc=misc.filesystem_encoding())) # If no instance of QApplication exists, a segmentation fault seems to always # occur. So we create one. if QCoreApplication.instance() is None: app = QApplication([]) # Register the fonts bundled with OpenSesame if font_database is None: font_database = QFontDatabase() for font in FONTS: try: path = exp.resource(font + u'.ttf') except: warnings.warn(u'Font %s not found' % font) continue font_id = font_database.addApplicationFont(path) if font_id < 0: warnings.warn(u'Failed to load font %s' % font) continue font_families = font_database.applicationFontFamilies(font_id) if not font_families: warnings.warn(u'Font %s contains no families' % font) continue font_substitutions.append((font_families[0], font))
def set_paths(): from qtpy import QtCore from libopensesame import misc # Add the folder that contains the OpenSesame modules to the path. This is # generally only necessary if OpenSesame is directly run from source, # instead from an installation. if os.path.exists(os.path.join(os.getcwd(), 'libopensesame')): sys.path.insert(0, os.getcwd()) # Add the Qt plugin folders to the library path, if they exists. Where # these folders are depends on the version of Qt4, but these are two # possible locations. qt_plugin_path = os.path.join(os.path.dirname(sys.executable), 'Library', 'plugins') if os.path.isdir(qt_plugin_path): QtCore.QCoreApplication.addLibraryPath( safe_decode(qt_plugin_path, enc=misc.filesystem_encoding())) qt_plugin_path = os.path.join(os.path.dirname(sys.executable), 'Library', 'lib', 'qt4', 'plugins') if os.path.isdir(qt_plugin_path): QtCore.QCoreApplication.addLibraryPath( safe_decode(qt_plugin_path, enc=misc.filesystem_encoding()))
def import_plugin(plugin, _type=u'plugins'): """ Imports plugin module Arguments: plugin -- the name of the plugin """ import imp plugin = str(plugin) folder = plugin_folder(plugin, _type=_type) for tmpl in src_templates: if os.path.exists(os.path.join(folder, tmpl % plugin)): path = os.path.join(folder, tmpl % plugin) if not py3: path = safe_encode(path, enc=misc.filesystem_encoding()) return imp.load_source(plugin, path) for tmpl in bytecode_templates: if os.path.exists(os.path.join(folder, tmpl % plugin)): path = os.path.join(folder, tmpl % plugin) if not py3: path = safe_encode(path, enc=misc.filesystem_encoding()) return imp.load_compiled(plugin, path)
def event_startup(self): """ desc: Called on startup. """ # Open an experiment if it has been specified as a command line argument # and suppress the new wizard in that case. if len(sys.argv) >= 2 and os.path.isfile(sys.argv[1]): path = safe_decode(sys.argv[1], enc=misc.filesystem_encoding(), errors=u'ignore') self.main_window.open_file(path=path) return self.activate()
def render(self): """ desc: Draws the widget. """ _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.exists(_path): raise osexception( u'No valid path has been specified in image widget') x, y, w, h = self.rect x += w / 2 y += h / 2 self.form.canvas.image(_path, x=x, y=y, scale=self.scale, center=True) if self.frame: self.draw_frame(self.rect)
def plugin_folders(only_existing=True): """ Returns a list of plugin folders. Keywords arguments: only_existing -- Specifies if only existing folders should be returned. (default=True) Returns: A list of folders. """ l = [] # For all platforms, the plugins folder relative to the working directory # should be searched path = os.path.join(os.getcwdu(), u'plugins') if not only_existing or os.path.exists(path): l.append(path) if os.name == u'posix' and u'HOME' in os.environ: # Regular Linux distributions. TODO: How well does this apply to Mac OS? path = os.path.join(os.environ[u'HOME'], u'.opensesame', u'plugins') if not only_existing or os.path.exists(path): l.append(path) path = u'/usr/share/opensesame/plugins' if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'posix' and u'HOME' not in os.environ: # Android can be recognized by the fact that the HOME variable is not # available. We can simply use the relative path `plugins`, which will # (always?) point to `/data/data/nl.cogsci.nl/opensesame/files/plugins` path = u'plugins' if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'nt': # Windows path = os.path.join(os.environ[u'APPDATA'].decode( \ misc.filesystem_encoding()), u'.opensesame', u'plugins') if not only_existing or os.path.exists(path): l.append(path) return l
def render(self): """ desc: Draws the widget. """ _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.exists(_path): raise osexception( u'No valid path has been specified in image widget') x, y, w, h = self.rect x += w/2 y += h/2 self.form.canvas.image(_path, x=x, y=y, scale=self.scale, center=True) if self.frame: self.draw_frame(self.rect)
def _init_canvas_elements(self): """ desc: Initializes all canvas elements. """ _path = safe_str(self.path, enc=misc.filesystem_encoding()) if not os.path.exists(_path): raise osexception( u'No valid path has been specified in image widget') x, y, w, h = self.rect x += w / 2 y += h / 2 print(_path) self.canvas.add_element( ImageElement(_path, x=x, y=y, scale=self.scale, center=True).construct(self.canvas)) if self.frame: self._update_frame(self.rect)
def __init__(self, main_window, theme=None): """ Constructor Arguments: main_window -- the main_window object Keyword arguments: theme -- the theme to be used or None to use config (default=None) """ self.main_window = main_window self.fallback_icon = QtGui.QIcon(os.path.join(misc.resource(u"theme"), u"fallback.png")) if theme is None: self.theme = config.get_config(u"theme") else: self.theme = theme self.theme_folder = misc.resource(os.path.join(u"theme", \ self.theme)) debug.msg(u"theme = '%s' (%s)" % (self.theme, self.theme_folder)) # The theme folder must exist, and contain a file called __theme__.py, # if not, we fall back to the default theme, which is assumed to always # exist. if self.theme_folder is None or not os.path.exists( os.path.join(self.theme_folder, u'__theme__.py')): debug.msg(u"theme '%s' does not exist, using 'default'" % theme, \ reason=u"warning") self.theme = u"default" self.theme_folder = misc.resource(os.path.join(u"theme", \ self.theme)) self.theme_info = os.path.join(self.theme_folder, u"__theme__.py") if os.path.exists(self.theme_info): info = imp.load_source(self.theme, safe_str(self.theme_info, enc=misc.filesystem_encoding())) with open(os.path.join(self.theme_folder, info.qss)) as fd: self._qss = fd.read() self._icon_map = info.icon_map self._icon_theme = info.icon_theme self.load_icon_map() self.apply_theme(self.main_window)
def __init__(self, main_window, theme=None): """ Constructor Arguments: main_window -- the main_window object Keyword arguments: theme -- the theme to be used or None to use config (default=None) """ self.main_window = main_window self.fallback_icon = QtGui.QIcon( os.path.join(misc.resource(u"theme"), u"fallback.png")) if theme is None: self.theme = config.get_config(u"theme") else: self.theme = theme self.theme_folder = misc.resource(os.path.join(u"theme", \ self.theme)) debug.msg(u"theme = '%s' (%s)" % (self.theme, self.theme_folder)) # The theme folder must exist, and contain a file called __theme__.py, # if not, we fall back to the default theme, which is assumed to always # exist. if self.theme_folder is None or not os.path.exists( os.path.join(self.theme_folder, u'__theme__.py')): debug.msg(u"theme '%s' does not exist, using 'default'" % theme, \ reason=u"warning") self.theme = u"default" self.theme_folder = misc.resource(os.path.join(u"theme", \ self.theme)) self.theme_info = os.path.join(self.theme_folder, u"__theme__.py") if os.path.exists(self.theme_info): info = imp.load_source( self.theme, safe_str(self.theme_info, enc=misc.filesystem_encoding())) with safe_open(os.path.join(self.theme_folder, info.qss)) as fd: self._qss = fd.read() self._icon_map = info.icon_map self._icon_theme = info.icon_theme self.load_icon_map() self.apply_theme(self.main_window)
def __init__(self, experiment, src, **playback_args): if src is not None: if isinstance(src, basestring): if not os.path.exists(src): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' does not exist" \ % src) if os.path.splitext(src)[1].lower() not in (".ogg", ".wav"): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' is not an .ogg or .wav file" \ % src) # The mixer chokes on unicode pathnames that contain special # characters. To avoid this we convert to str with the # filesystem encoding. (Python 2 only). if not py3 and isinstance(src, str): import sys src = src.encode(misc.filesystem_encoding()) self.sound = mixer.Sound(src) sampler.sampler.__init__(self, experiment, src, **playback_args) self.keyboard = keyboard(experiment)
def __init__(self, plugin_file=None): """ desc: Constructor. arguments: plugin_file: The location of the plugin script file. """ if plugin_file is not None: # The __file__ variable is generally a str, which will cause unicode # errors. Therefore, convert this here if necessary. plugin_file = safe_decode(plugin_file, enc=misc.filesystem_encoding()) # These lines makes sure that the icons and help file are recognized # by OpenSesame. self.plugin_folder = os.path.dirname(plugin_file) self.experiment.resources[u'%s.html' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.html' \ % self.item_type) self.experiment.resources[u'%s.md' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.md' \ % self.item_type) # Install a translation file if there is one. Most plugins have # their translations as part of the OpenSesame main translations. # However, separate plugins can bring their own translation. translation_file = os.path.join(self.plugin_folder, u'resources', u'locale', u'%s.qm' % self.main_window._locale) if os.path.exists(translation_file): translator = QtCore.QTranslator() translator.load(translation_file) QtCore.QCoreApplication.installTranslator(translator) self.init_item_icon() else: self.qicon = None self.lock = False qtitem.qtitem.__init__(self)
def __init__(self, experiment, src): """<DOC> Initializes the sampler with a specified file. Arguments: experiment -- An instance of libopensesame.experiment.experiment. src -- A path to a .wav or .ogg file. Example: >>> from openexp.sampler import sampler >>> src = exp.get_file('my_sound.ogg') >>> my_sampler = sampler(exp, src) </DOC>""" if src != None: if not os.path.exists(src): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' does not exist" \ % src) if os.path.splitext(src)[1].lower() not in (".ogg", ".wav"): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' is not an .ogg or .wav file" \ % src) # The mixer chokes on unicode pathnames that contain special # characters. To avoid this we convert to str with the filesystem # encoding. if isinstance(src, unicode): import sys src = src.encode(misc.filesystem_encoding()) self.sound = mixer.Sound(src) self.experiment = experiment self.keyboard = keyboard(experiment) self._stop_after = 0 self._fade_in = 0 self._volume = 1.0
def __init__(self, experiment, src): if src != None: if isinstance(src, basestring): if not os.path.exists(src): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' does not exist" \ % src) if os.path.splitext(src)[1].lower() not in (".ogg", ".wav"): raise osexception( \ u"openexp._sampler.legacy.__init__() the file '%s' is not an .ogg or .wav file" \ % src) # The mixer chokes on unicode pathnames that contain special # characters. To avoid this we convert to str with the filesystem # encoding. if isinstance(src, unicode): import sys src = src.encode(misc.filesystem_encoding()) self.sound = mixer.Sound(src) self.experiment = experiment self.keyboard = keyboard(experiment) self._stop_after = 0 self._fade_in = 0 self._volume = 1.0
def __init__(self, plugin_file=None): """ Constructor. Arguments: plugin_file -- The path to the plugin script. (default=None) """ if plugin_file is not None: # The __file__ variable is generally a str, which will cause unicode # errors. Therefore, convert this here if necessary. plugin_file = safe_decode(plugin_file, enc=misc.filesystem_encoding()) # These lines makes sure that the icons and help file are recognized # by OpenSesame. self.plugin_folder = os.path.dirname(plugin_file) icon16 = os.path.join( self.plugin_folder, u'%s.png' % self.item_type) icon32 = os.path.join( self.plugin_folder, u'%s_large.png' % self.item_type) self.experiment.resources[u'%s.png' % self.item_type] = icon16 self.experiment.resources[u'%s_large.png' % self.item_type] = icon32 self.experiment.resources[u'%s.html' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.html' \ % self.item_type) self.experiment.resources[u'%s.md' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.md' \ % self.item_type) self.qicon = QtGui.QIcon() self.qicon.addFile(icon16, QtCore.QSize(16,16)) self.qicon.addFile(icon32, QtCore.QSize(32,32)) else: self.qicon = None self.lock = False qtitem.qtitem.__init__(self)
def __init__(self, plugin_file=None): """ Constructor. Arguments: plugin_file -- The path to the plugin script. (default=None) """ if plugin_file is not None: # The __file__ variable is generally a str, which will cause unicode # errors. Therefore, convert this here if necessary. plugin_file = safe_decode(plugin_file, enc=misc.filesystem_encoding()) # These lines makes sure that the icons and help file are recognized # by OpenSesame. self.plugin_folder = os.path.dirname(plugin_file) icon16 = os.path.join(self.plugin_folder, u'%s.png' % self.item_type) icon32 = os.path.join(self.plugin_folder, u'%s_large.png' % self.item_type) self.experiment.resources[u'%s.png' % self.item_type] = icon16 self.experiment.resources[u'%s_large.png' % self.item_type] = icon32 self.experiment.resources[u'%s.html' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.html' \ % self.item_type) self.experiment.resources[u'%s.md' % self.item_type] = \ os.path.join(self.plugin_folder, u'%s.md' \ % self.item_type) self.qicon = QtGui.QIcon() self.qicon.addFile(icon16, QtCore.QSize(16, 16)) self.qicon.addFile(icon32, QtCore.QSize(32, 32)) else: self.qicon = None self.lock = False qtitem.qtitem.__init__(self)
""" from libopensesame import item, generic_response, exceptions, debug, misc from libqtopensesame import qtplugin from libqtopensesame.misc import _ from openexp.keyboard import keyboard import imp import os import os.path from PyQt4 import QtGui, QtCore, uic # First try to load libboks from source, from the plug-in folder. If this fails, # try a plain import statement. try: libboks = imp.load_source(u'libboks', os.path.join(os.path.dirname( \ __file__).decode(misc.filesystem_encoding()), u'libboks.py')) except: import libboks class boks(item.item, generic_response.generic_response): """A plug-in for using the Boks""" description = u'Collects input from a boks' def __init__(self, name, experiment, script=None): """ Constructor. Arguments:
def resume_init(self): """Resume GUI initialization""" from libopensesame import misc from libqtopensesame.misc import theme from libqtopensesame.extensions import extension_manager import random # Make sure that icons are shown in context menu, regardless of the # system settings. This is necessary, because Ubuntu doesn't show menu # icons by default. QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus, False) # Do a few things to customize QProgEdit behavior: # - Register the bundled monospace font (Droid Sans Mono) # - Make sure that QProgEdit doesn't complain about some standard names # - Ignore undefined name warnings, which don't play well with # OpenSesame's single workspace QtGui.QFontDatabase.addApplicationFont(misc.resource(u'mono.ttf')) from QProgEdit import validate validate.addPythonBuiltins([u'exp', u'win', u'self']) if hasattr(validate, u'setPyFlakesFilter'): validate.setPyFlakesFilter( lambda msg: msg.message == u'undefined name %r') # Initialize random number generator random.seed() # Check the filesystem encoding for debugging purposes debug.msg(u'filesystem encoding: %s' % misc.filesystem_encoding()) # # Parse the command line # self.parse_command_line() # # # Restore the configuration # self.restore_config() self.set_style() self.set_warnings() # self.set_locale() # Setup the UI self.load_ui(u'misc.main_window') self.theme = theme.theme(self, self.options._theme) self.ui.itemtree.setup(self) self.ui.console.setup(self) self.ui.tabwidget.main_window = self # Determine the home folder self.home_folder = libopensesame.misc.home_folder() # Create .opensesame folder if it doesn't exist yet if not os.path.exists(os.path.join(self.home_folder, u".opensesame")): os.mkdir(os.path.join(self.home_folder, u".opensesame")) # Set the filter-string for opening and saving files self.save_file_filter = u'OpenSesame files (*.osexp)' self.open_file_filter = \ u'OpenSesame files (*.osexp *.opensesame.tar.gz *.opensesame)' # Set the window message self._read_only = False self.window_message(_(u"New experiment")) # Set the window icon self.setWindowIcon(self.theme.qicon(u"opensesame")) # Make the connections self.ui.itemtree.structure_change.connect(self.update_overview_area) self.ui.action_quit.triggered.connect(self.close) self.ui.action_open.triggered.connect(self.open_file) self.ui.action_save.triggered.connect(self.save_file) self.ui.action_save_as.triggered.connect(self.save_file_as) self.ui.action_run.triggered.connect(self.run_experiment) self.ui.action_run_in_window.triggered.connect( self.run_experiment_in_window) self.ui.action_run_quick.triggered.connect(self.run_quick) self.ui.action_kill.triggered.connect(self.kill_experiment) self.ui.action_enable_auto_response.triggered.connect( self.set_auto_response) self.ui.action_close_current_tab.triggered.connect( self.ui.tabwidget.close_current) self.ui.action_close_all_tabs.triggered.connect( self.ui.tabwidget.close_all) self.ui.action_close_other_tabs.triggered.connect( self.ui.tabwidget.close_other) self.ui.action_onetabmode.triggered.connect( self.ui.tabwidget.toggle_onetabmode) self.ui.action_show_overview.triggered.connect(self.toggle_overview) self.ui.action_show_pool.triggered.connect(self.toggle_pool) self.ui.action_show_stdout.triggered.connect(self.refresh_stdout) self.ui.action_preferences.triggered.connect( self.ui.tabwidget.open_preferences) # Setup console self.ui.button_help_console.clicked.connect( self.ui.tabwidget.open_stdout_help) self.ui.button_reset_console.clicked.connect(self.ui.console.reset) # Setup the overview area self.ui.dock_overview.show() self.ui.dock_overview.visibilityChanged.connect( self.ui.action_show_overview.setChecked) # Setup the file pool from libqtopensesame.widgets.pool_widget import pool_widget self.ui.dock_pool.hide() self.ui.dock_pool.visibilityChanged.connect( self.ui.action_show_pool.setChecked) self.ui.pool_widget = pool_widget(self) self.ui.dock_pool.setWidget(self.ui.pool_widget) # Uncheck the debug window button on debug window close self.ui.dock_stdout.hide() self.ui.dock_stdout.visibilityChanged.connect( self.ui.action_show_stdout.setChecked) # Initialize keyboard shortcuts self.ui.shortcut_itemtree = QtWidgets.QShortcut( QtGui.QKeySequence(), self, self.focus_overview_area) self.ui.shortcut_tabwidget = QtWidgets.QShortcut( QtGui.QKeySequence(), self, self.ui.tabwidget.focus) self.ui.shortcut_stdout = QtWidgets.QShortcut(QtGui.QKeySequence(), self, self.focus_debug_window) self.ui.shortcut_pool = QtWidgets.QShortcut(QtGui.QKeySequence(), self, self.focus_file_pool) # Create the initial experiment, which is the default template. Because # not all backends are supported under Python 3, we use a different # backend for each. if py3: tmpl = u'default-py3.osexp' else: tmpl = u'default.osexp' with safe_open(misc.resource(os.path.join(u'templates', tmpl)), u'r') as fd: self.experiment = experiment.experiment(self, u'New experiment', fd.read()) self.experiment.build_item_tree() self.ui.itemtree.default_fold_state() # Miscellaneous initialization self.restore_state() self.update_recent_files() self.set_unsaved(False) self.init_custom_fonts() # Initialize extensions self.extension_manager = extension_manager(self) self.extension_manager.fire(u'startup')
def resume_init(self): """Resume GUI initialization""" from libopensesame import misc from libqtopensesame.misc import theme from libqtopensesame.extensions import extension_manager import platform import random # Set some initial variables self.current_path = None self.version = misc.version self.codename = misc.codename self.lock_refresh = False self.unsaved_changes = False # Make sure that QProgEdit doesn't complain about some standard names from QProgEdit import validate validate.addPythonBuiltins([u'exp', u'win', u'self']) # Initialize random number generator random.seed() # Check the filesystem encoding for debugging purposes debug.msg(u'filesystem encoding: %s' % misc.filesystem_encoding()) # Parse the command line self.parse_command_line() # Restore the configuration self.restore_config() # Setup the UI self.load_ui(u'misc.main_window') self.ui.itemtree.setup(self) self.ui.tabwidget.main_window = self # Load a theme self.theme = theme.theme(self, self.options._theme) # Determine the home folder self.home_folder = libopensesame.misc.home_folder() # Create .opensesame folder if it doesn't exist yet if not os.path.exists(os.path.join(self.home_folder, u".opensesame")): os.mkdir(os.path.join(self.home_folder, u".opensesame")) # Set the filter-string for opening and saving files self.file_type_filter = \ u"OpenSesame files (*.opensesame.tar.gz *.opensesame);;OpenSesame script and file pool (*.opensesame.tar.gz);;OpenSesame script (*.opensesame)" self.file_type_filter_script = u"OpenSesame script (*.opensesame)" self.file_type_filter_pool = \ u"OpenSesame script and file pool (*.opensesame.tar.gz)" # Set the window message self.window_message(_(u"Welcome to OpenSesame %s") % self.version) # Set the window icon self.setWindowIcon(self.theme.qicon(u"opensesame")) # Make the connections self.ui.itemtree.structure_change.connect(self.update_overview_area) self.ui.action_quit.triggered.connect(self.close) self.ui.action_new.triggered.connect(self.new_file) self.ui.action_open.triggered.connect(self.open_file) self.ui.action_save.triggered.connect(self.save_file) self.ui.action_save_as.triggered.connect(self.save_file_as) self.ui.action_run.triggered.connect(self.run_experiment) self.ui.action_run_in_window.triggered.connect( self.run_experiment_in_window) self.ui.action_run_quick.triggered.connect(self.run_quick) self.ui.action_enable_auto_response.triggered.connect( self.set_auto_response) self.ui.action_close_current_tab.triggered.connect( self.ui.tabwidget.close_current) self.ui.action_close_all_tabs.triggered.connect( self.ui.tabwidget.close_all) self.ui.action_close_other_tabs.triggered.connect( self.ui.tabwidget.close_other) self.ui.action_onetabmode.triggered.connect( self.ui.tabwidget.toggle_onetabmode) self.ui.action_show_overview.triggered.connect(self.toggle_overview) self.ui.action_show_variable_inspector.triggered.connect( self.refresh_variable_inspector) self.ui.action_show_pool.triggered.connect(self.refresh_pool) self.ui.action_show_stdout.triggered.connect(self.refresh_stdout) self.ui.action_preferences.triggered.connect( self.ui.tabwidget.open_preferences) self.ui.button_help_stdout.clicked.connect( self.ui.tabwidget.open_stdout_help) # Setup the overview area self.ui.dock_overview.show() self.ui.dock_overview.visibilityChanged.connect( \ self.ui.action_show_overview.setChecked) # Setup the variable inspector from libqtopensesame.widgets.variable_inspector import \ variable_inspector self.ui.variable_inspector = variable_inspector(self) self.ui.dock_variable_inspector.hide() self.ui.dock_variable_inspector.visibilityChanged.connect( self.ui.action_show_variable_inspector.setChecked) self.ui.dock_variable_inspector.setWidget(self.ui.variable_inspector) # Setup the file pool from libqtopensesame.widgets.pool_widget import pool_widget self.ui.dock_pool.hide() self.ui.dock_pool.visibilityChanged.connect( self.ui.action_show_pool.setChecked) self.ui.pool_widget = pool_widget(self) self.ui.dock_pool.setWidget(self.ui.pool_widget) # Uncheck the debug window button on debug window close self.ui.dock_stdout.visibilityChanged.connect( \ self.ui.action_show_stdout.setChecked) # Initialize keyboard shortcuts self.ui.shortcut_itemtree = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.itemtree.setFocus) self.ui.shortcut_tabwidget = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.tabwidget.setFocus) self.ui.shortcut_stdout = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.edit_stdout.setFocus) self.ui.shortcut_variables = QtGui.QShortcut( \ QtGui.QKeySequence(), self, \ self.ui.variable_inspector.set_focus()) self.ui.shortcut_pool = QtGui.QShortcut( \ QtGui.QKeySequence(), self, \ self.ui.pool_widget.ui.edit_pool_filter.setFocus) # Create the initial experiment, which is the default template. self.experiment = experiment.experiment(self, u"New experiment", \ open(misc.resource(os.path.join(u"templates", \ u"default.opensesame")), u"r").read()) self.experiment.build_item_tree() # Miscellaneous initialization self.restore_state() self.update_recent_files() self.set_unsaved(False) self.init_custom_fonts() self.ui.variable_inspector.refresh() # Initialize extensions self.extension_manager = extension_manager(self) self.extension_manager.fire(u'startup')
def open(self, src): """ desc: | Opens a file from a source, which can be any of the following: - A definition string - The name of a plain-text file - The name of a .tar.gz archive, which contains the script and the file pool. arguments: src: The source. returns: desc: A defition string. type: str """ # If the path is not a path at all, but a string containing # the script, return it. Also, convert the path back to Unicode before # returning. if not os.path.exists(src): debug.msg(u'opening from unicode string') self.experiment_path = None return safe_decode(src, errors=u'replace') try: tar = tarfile.open(src, u'r:gz') except tarfile.ReadError: # If the file wasn't a .tar.gz, then it must be a plain-text file debug.msg(u"opening plain-text experiment") with open(src, universal_newline_mode) as fd: return safe_decode(fd.read()) debug.msg(u"opening .tar.gz archive") # If the file is a .tar.gz archive, extract the pool to the pool folder # and return the contents of opensesame.script. tar = tarfile.open(src, u'r:gz') for name in tar.getnames(): # Here, all paths except name are Unicode. In addition, fname is # Unicode from_asciid, because the files as saved are Unicode # sanitized (see save()). uname = safe_decode(name) folder, fname = os.path.split(uname) fname = self._syntax.from_ascii(fname) if folder == u"pool": # NOTE: When merging into `ising`, this needs to be ported to # the py3compat system, and Python 3 compatibility needs to be # checked. debug.msg(u"extracting '%s'" % uname) pool_folder = safe_str(self.pool.folder(), enc=misc.filesystem_encoding()) from_name = safe_str(os.path.join(self.pool.folder(), uname), enc=misc.filesystem_encoding()) to_name = safe_str(os.path.join(self.pool.folder(), fname), enc=misc.filesystem_encoding()) tar.extract(name, pool_folder) os.rename(from_name, to_name) os.rmdir(os.path.join(self.pool.folder(), folder)) script_path = os.path.join(self.pool.folder(), u"script.opensesame") tar.extract(u"script.opensesame", self.pool.folder()) with open(script_path, universal_newline_mode) as fd: script = safe_decode(fd.read()) os.remove(script_path) self.experiment_path = os.path.dirname(src) return script
def resume_init(self): """Resume GUI initialization""" from libopensesame import misc from libqtopensesame.misc import theme from libqtopensesame.extensions import extension_manager import random # Make sure that icons are shown in context menu, regardless of the # system settings. This is necessary, because Ubuntu doesn't show menu # icons by default. QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus, False) # Add the Qt plugin folders to the library path, if they exists. Where # these folders are depends on the version of Qt4, but these are two # possible locations. qt_plugin_path = os.path.join( os.path.dirname(sys.executable), 'Library', 'plugins') if os.path.isdir(qt_plugin_path): QtCore.QCoreApplication.addLibraryPath(qt_plugin_path) qt_plugin_path = os.path.join( os.path.dirname(sys.executable), 'Library', 'lib', 'qt4', 'plugins') if os.path.isdir(qt_plugin_path): QtCore.QCoreApplication.addLibraryPath(qt_plugin_path) # Do a few things to customize QProgEdit behavior: # - Register the bundled monospace font (Droid Sans Mono) # - Make sure that QProgEdit doesn't complain about some standard names # - Ignore undefined name warnings, which don't play well with # OpenSesame's single workspace QtGui.QFontDatabase.addApplicationFont(misc.resource(u'mono.ttf')) from QProgEdit import validate validate.addPythonBuiltins([u'exp', u'win', u'self']) if hasattr(validate, u'setPyFlakesFilter'): validate.setPyFlakesFilter( lambda msg: msg.message == u'undefined name %r') # Initialize random number generator random.seed() # Check the filesystem encoding for debugging purposes debug.msg(u'filesystem encoding: %s' % misc.filesystem_encoding()) # # Parse the command line # self.parse_command_line() # # # Restore the configuration # self.restore_config() self.set_style() self.set_warnings() # self.set_locale() # Setup the UI self.load_ui(u'misc.main_window') self.theme = theme.theme(self, self.options._theme) self.ui.itemtree.setup(self) self.ui.console.setup(self) self.ui.tabwidget.main_window = self # Determine the home folder self.home_folder = libopensesame.misc.home_folder() # Create .opensesame folder if it doesn't exist yet if not os.path.exists(os.path.join(self.home_folder, u".opensesame")): os.mkdir(os.path.join(self.home_folder, u".opensesame")) # Set the filter-string for opening and saving files self.save_file_filter =u'OpenSesame files (*.osexp)' self.open_file_filter = \ u'OpenSesame files (*.osexp *.opensesame.tar.gz *.opensesame)' # Set the window message self._read_only = False self.window_message(_(u"New experiment")) # Set the window icon self.setWindowIcon(self.theme.qicon(u"opensesame")) # Make the connections self.ui.itemtree.structure_change.connect(self.update_overview_area) self.ui.action_quit.triggered.connect(self.close) self.ui.action_open.triggered.connect(self.open_file) self.ui.action_save.triggered.connect(self.save_file) self.ui.action_save_as.triggered.connect(self.save_file_as) self.ui.action_run.triggered.connect(self.run_experiment) self.ui.action_run_in_window.triggered.connect( self.run_experiment_in_window) self.ui.action_run_quick.triggered.connect(self.run_quick) self.ui.action_enable_auto_response.triggered.connect( self.set_auto_response) self.ui.action_close_current_tab.triggered.connect( self.ui.tabwidget.close_current) self.ui.action_close_all_tabs.triggered.connect( self.ui.tabwidget.close_all) self.ui.action_close_other_tabs.triggered.connect( self.ui.tabwidget.close_other) self.ui.action_onetabmode.triggered.connect( self.ui.tabwidget.toggle_onetabmode) self.ui.action_show_overview.triggered.connect(self.toggle_overview) self.ui.action_show_pool.triggered.connect( self.toggle_pool) self.ui.action_show_stdout.triggered.connect(self.refresh_stdout) self.ui.action_preferences.triggered.connect( self.ui.tabwidget.open_preferences) # Setup console self.ui.button_help_console.clicked.connect( self.ui.tabwidget.open_stdout_help) self.ui.button_reset_console.clicked.connect( self.ui.console.reset) # Setup the overview area self.ui.dock_overview.show() self.ui.dock_overview.visibilityChanged.connect( self.ui.action_show_overview.setChecked) # Setup the file pool from libqtopensesame.widgets.pool_widget import pool_widget self.ui.dock_pool.hide() self.ui.dock_pool.visibilityChanged.connect( self.ui.action_show_pool.setChecked) self.ui.pool_widget = pool_widget(self) self.ui.dock_pool.setWidget(self.ui.pool_widget) # Uncheck the debug window button on debug window close self.ui.dock_stdout.hide() self.ui.dock_stdout.visibilityChanged.connect( self.ui.action_show_stdout.setChecked) # Initialize keyboard shortcuts self.ui.shortcut_itemtree = QtWidgets.QShortcut(QtGui.QKeySequence(), self, self.focus_overview_area) self.ui.shortcut_tabwidget = QtWidgets.QShortcut( QtGui.QKeySequence(), self, self.ui.tabwidget.focus) self.ui.shortcut_stdout = QtWidgets.QShortcut(QtGui.QKeySequence(), self, self.focus_debug_window) self.ui.shortcut_pool = QtWidgets.QShortcut(QtGui.QKeySequence(), self, self.focus_file_pool) # Create the initial experiment, which is the default template. Because # not all backends are supported under Python 3, we use a different # backend for each. if py3: tmpl = u'default-py3.osexp' else: tmpl = u'default.osexp' with safe_open(misc.resource(os.path.join(u'templates', tmpl)), u'r') as fd: self.experiment = experiment.experiment(self, u'New experiment', fd.read()) self.experiment.build_item_tree() self.ui.itemtree.default_fold_state() # Miscellaneous initialization self.restore_state() self.update_recent_files() self.set_unsaved(False) self.init_custom_fonts() # Initialize extensions self.extension_manager = extension_manager(self) self.extension_manager.fire(u'startup')
def __init__(self, name=u'experiment', string=None, pool_folder=None, experiment_path=None, fullscreen=False, auto_response=False, logfile=u'defaultlog.csv', subject_nr=0, items=None, workspace=None, resources={}): """ desc: Constructor. The experiment is created automatically be OpenSesame and you will generally not need to create it yourself. keywords: name: desc: The name of the experiment. type: [str, unicode] string: desc: A string containing the experiment definition, the name of an OpenSesame experiment file, or `None` to create a blank experiment. type: [str, unicode, NoneType] pool_folder: desc: A specific folder to be used for the file pool, or `None` to use a new temporary folder. type: [str, unicode, NoneType] experiment_path: desc: The path of the experiment file. This will need to be specified even if a filename was passed using the `string` keyword. type: [str, unicode, NoneType] fullscreen: desc: Indicates whether the experiment should be executed in fullscreen. type: bool auto_response: desc: Indicates whether auto-response mode should be enabled. type: bool logfile: desc: The logfile path. type: [unicode, str] subject_nr: desc: The subject number. type: int items: desc: An `item_store` object to be used for storing items internally, or `None` to create a new item store. type: [item_store, NoneType] workspace: desc: A `python_workspace` object to be used for executing custom Python code, or `None` to create a new workspace. type: [python_workspace, NoneType] resources: desc: A dictionary with names as keys and paths as values. This serves as a look-up table for resources. type: dict """ global pool_folders if items == None: self.items = item_store(self) else: self.items = items if workspace == None: self.python_workspace = python_workspace(self) else: self.python_workspace = workspace self.running = False self.auto_response = auto_response self.plugin_folder = u'plugins' self.start_response_interval = None self.cleanup_functions = [] self.restart = False self.title = u'My Experiment' self.transparent_variables = u'no' self.bidi = u'no' self.resources = resources # Set default variables self.start = u'experiment' # Sound parameters self.sound_freq = 48000 self.sound_sample_size = -16 # Negative values mean signed self.sound_channels = 2 self.sound_buf_size = 1024 # Backend parameters self.canvas_backend = u'xpyriment' self.keyboard_backend = u'legacy' self.mouse_backend = u'xpyriment' self.sampler_backend = u'legacy' self.synth_backend = u'legacy' # Save the date and time, and the version of OpenSesame self.datetime = time.strftime(u'%c').decode(self.encoding, u'ignore') self.opensesame_version = misc.version self.opensesame_codename = misc.codename # Display parameters self.width = 1024 self.height = 768 self.background = u'black' self.foreground = u'white' self.fullscreen = fullscreen # Font parameters self.font_size = 18 self.font_family = u'mono' self.font_italic = u'no' self.font_bold = u'no' self.font_underline = u'no' # Logfile parameters self._log = None self.logfile = logfile # This is some duplication of the option parser in qtopensesame, # but nevertheless keep it so we don't need qtopensesame self.debug = debug.enabled self._stack = debug.stack # Pool folder if pool_folder == None: # On some systems tempfile.mkdtemp() triggers a UnicodeDecodeError. # This is resolved by passing the dir explicitly as a Unicode # string. This fix has been adapted from: # - <http://bugs.python.org/issue1681974> self.pool_folder = tempfile.mkdtemp(suffix= \ u'.opensesame_pool', dir=tempfile.gettempdir().decode( \ encoding=misc.filesystem_encoding())) pool_folders.append(self.pool_folder) debug.msg(u'creating new pool folder') else: debug.msg(u'reusing existing pool folder') self.pool_folder = pool_folder debug.msg(u'pool folder is \'%s\'' % self.pool_folder) string = self.open(string) item.item.__init__(self, name, self, string) # Default subject info self.set_subject(subject_nr) # Restore experiment path if experiment_path != None: self.fallback_pool_folder = os.path.join(experiment_path, u'__pool__') if os.path.exists(self.fallback_pool_folder): debug.msg(u'Using fallback pool folder: %s' \ % self.fallback_pool_folder) else: self.fallback_pool_folder = None self.experiment_path = experiment_path else: self.fallback_pool_folder = None
def plugin_folders(only_existing=True, _type=u'plugins'): """ desc: Returns a list of plugin folders. keywords: only_existing: desc: Specifies if only existing folders should be returned. type: bool _type: desc: Indicates whether runtime plugins ('plugins') or GUI extensions ('extensions') should be listed. type: [str, unicode] returns: desc: A list of folders. type: list """ l = [] # Build a list of default plugin/ extension folders for folder in misc.base_folders: path = os.path.join(folder, u'opensesame_%s' % _type) if os.path.exists(path): l.append(path) # Get the environment variables if _type == u'plugins': key = u'OPENSESAME_PLUGIN_PATH' else: key = u'OPENSESAME_EXTENSION_PATH' if key in os.environ: for path in os.environ[key].split(';'): path = safe_decode(path, enc=misc.filesystem_encoding()) if os.path.exists(path): l.append(path) if os.name == u'posix' and u'HOME' in os.environ: # Regular Linux distributions. TODO: How well does this apply to Mac OS? path = os.path.join(os.environ[u'HOME'], u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) path = u'/usr/share/opensesame/%s' % _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'posix' and u'HOME' not in os.environ: # Android can be recognized by the fact that the HOME variable is not # available. We can simply use the relative path `plugins`, which will # (always?) point to `/data/data/nl.cogsci.nl/opensesame/files/plugins` path = _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'nt': # Windows path = os.path.join(safe_decode(os.environ[u'APPDATA'], enc=misc.filesystem_encoding()), u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) return l
def plugin_folders(only_existing=True, _type=u'plugins'): """ desc: Returns a list of plugin folders. keywords: only_existing: desc: Specifies if only existing folders should be returned. type: bool _type: desc: Indicates whether runtime plugins ('plugins') or GUI extensions ('extensions') should be listed. type: [str, unicode] returns: desc: A list of folders. type: list """ l = [] # Build a list of default plugin/ extension folders for folder in misc.base_folders: path = os.path.join(folder, u'opensesame_%s' % _type) if os.path.exists(path): l.append(path) # Get the environment variables if _type == u'plugins': key = u'OPENSESAME_PLUGIN_PATH' else: key = u'OPENSESAME_EXTENSION_PATH' if key in os.environ: for path in os.environ[key].split(';'): path = safe_decode(path, enc=misc.filesystem_encoding()) if os.path.exists(path): l.insert(0, path) if os.name == u'posix' and u'HOME' in os.environ: # Regular Linux distributions. TODO: How well does this apply to Mac OS? path = os.path.join(os.environ[u'HOME'], u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) path = u'/usr/share/opensesame/%s' % _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'posix' and u'HOME' not in os.environ: # Android can be recognized by the fact that the HOME variable is not # available. We can simply use the relative path `plugins`, which will # (always?) point to `/data/data/nl.cogsci.nl/opensesame/files/plugins` path = _type if not only_existing or os.path.exists(path): l.append(path) elif os.name == u'nt': # Windows path = os.path.join(safe_decode(os.environ[u'APPDATA'], enc=misc.filesystem_encoding()), u'.opensesame', _type) if not only_existing or os.path.exists(path): l.append(path) return l
======= >>>>>>> 61437b7728a64a89e660f1dc0b55af5677e65dfe # This is some duplication of the option parser in qtopensesame, # but nevertheless keep it so we don't need qtopensesame self.debug = debug.enabled self._stack = debug.stack # Pool folder if pool_folder == None: # On some systems tempfile.mkdtemp() triggers a UnicodeDecodeError. # This is resolved by passing the dir explicitly as a Unicode # string. This fix has been adapted from: # - <http://bugs.python.org/issue1681974> self.pool_folder = tempfile.mkdtemp(suffix= \ u'.opensesame_pool', dir=tempfile.gettempdir().decode( \ encoding=misc.filesystem_encoding())) pool_folders.append(self.pool_folder) debug.msg(u'creating new pool folder') else: debug.msg(u'reusing existing pool folder') self.pool_folder = pool_folder debug.msg(u'pool folder is \'%s\'' % self.pool_folder) string = self.open(string) item.item.__init__(self, name, self, string) # Default subject info self.set_subject(subject_nr) # Restore experiment path if experiment_path != None: self.experiment_path = experiment_path
def resume_init(self): """Resume GUI initialization""" from libopensesame import misc from libqtopensesame.misc import theme from libqtopensesame.extensions import extension_manager import platform import random # Set some initial variables self.current_path = None self.version = misc.version self.codename = misc.codename self.lock_refresh = False self.unsaved_changes = False # Make sure that QProgEdit doesn't complain about some standard names from QProgEdit import validate validate.addPythonBuiltins([u'exp', u'win', u'self']) # Initialize random number generator random.seed() # Check the filesystem encoding for debugging purposes debug.msg(u'filesystem encoding: %s' % misc.filesystem_encoding()) # Parse the command line self.parse_command_line() # Restore the configuration self.restore_config() # Setup the UI self.load_ui(u'misc.main_window') self.ui.itemtree.setup(self) self.ui.tabwidget.main_window = self # Load a theme self.theme = theme.theme(self, self.options._theme) # Determine the home folder self.home_folder = libopensesame.misc.home_folder() # Create .opensesame folder if it doesn't exist yet if not os.path.exists(os.path.join(self.home_folder, u".opensesame")): os.mkdir(os.path.join(self.home_folder, u".opensesame")) # Set the filter-string for opening and saving files self.file_type_filter = \ u"OpenSesame files (*.opensesame.tar.gz *.opensesame);;OpenSesame script and file pool (*.opensesame.tar.gz);;OpenSesame script (*.opensesame)" # Set the window message self.window_message(_(u"Welcome to OpenSesame %s") % self.version) # Set the window icon self.setWindowIcon(self.theme.qicon(u"opensesame")) # Make the connections self.ui.itemtree.structure_change.connect(self.update_overview_area) self.ui.action_quit.triggered.connect(self.close) self.ui.action_new.triggered.connect(self.new_file) self.ui.action_open.triggered.connect(self.open_file) self.ui.action_save.triggered.connect(self.save_file) self.ui.action_save_as.triggered.connect(self.save_file_as) self.ui.action_run.triggered.connect(self.run_experiment) self.ui.action_run_in_window.triggered.connect( self.run_experiment_in_window) self.ui.action_run_quick.triggered.connect(self.run_quick) self.ui.action_enable_auto_response.triggered.connect( self.set_auto_response) self.ui.action_close_current_tab.triggered.connect( self.ui.tabwidget.close_current) self.ui.action_close_all_tabs.triggered.connect( self.ui.tabwidget.close_all) self.ui.action_close_other_tabs.triggered.connect( self.ui.tabwidget.close_other) self.ui.action_onetabmode.triggered.connect( self.ui.tabwidget.toggle_onetabmode) self.ui.action_show_overview.triggered.connect(self.toggle_overview) self.ui.action_show_variable_inspector.triggered.connect( self.refresh_variable_inspector) self.ui.action_show_pool.triggered.connect(self.refresh_pool) self.ui.action_show_stdout.triggered.connect(self.refresh_stdout) self.ui.action_preferences.triggered.connect( self.ui.tabwidget.open_preferences) self.ui.button_help_stdout.clicked.connect( self.ui.tabwidget.open_stdout_help) # Setup the overview area self.ui.dock_overview.show() self.ui.dock_overview.visibilityChanged.connect( \ self.ui.action_show_overview.setChecked) # Setup the variable inspector from libqtopensesame.widgets.variable_inspector import \ variable_inspector self.ui.variable_inspector = variable_inspector(self) self.ui.dock_variable_inspector.hide() self.ui.dock_variable_inspector.visibilityChanged.connect( self.ui.action_show_variable_inspector.setChecked) self.ui.dock_variable_inspector.setWidget(self.ui.variable_inspector) # Setup the file pool from libqtopensesame.widgets.pool_widget import pool_widget self.ui.dock_pool.hide() self.ui.dock_pool.visibilityChanged.connect( self.ui.action_show_pool.setChecked) self.ui.pool_widget = pool_widget(self) self.ui.dock_pool.setWidget(self.ui.pool_widget) # Uncheck the debug window button on debug window close self.ui.dock_stdout.visibilityChanged.connect( \ self.ui.action_show_stdout.setChecked) # Initialize keyboard shortcuts self.ui.shortcut_itemtree = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.itemtree.setFocus) self.ui.shortcut_tabwidget = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.tabwidget.setFocus) self.ui.shortcut_stdout = QtGui.QShortcut( \ QtGui.QKeySequence(), self, self.ui.edit_stdout.setFocus) self.ui.shortcut_variables = QtGui.QShortcut( \ QtGui.QKeySequence(), self, \ self.ui.variable_inspector.set_focus()) self.ui.shortcut_pool = QtGui.QShortcut( \ QtGui.QKeySequence(), self, \ self.ui.pool_widget.ui.edit_pool_filter.setFocus) # Create the initial experiment, which is the default template. self.experiment = experiment.experiment(self, u"New experiment", \ open(misc.resource(os.path.join(u"templates", \ u"default.opensesame")), u"r").read()) self.experiment.build_item_tree() # Miscellaneous initialization self.restore_state() self.update_recent_files() self.set_unsaved(False) self.init_custom_fonts() # Initialize extensions self.extension_manager = extension_manager(self) self.extension_manager.fire(u'startup')
def __init__(self, name=u'experiment', string=None, pool_folder=None, experiment_path=None, fullscreen=False, auto_response=False, logfile=u'defaultlog.csv', subject_nr=0): """<DOC> Constructor. The experiment is created automatically be OpenSesame and # you will generally not need to create it yourself. Keyword arguments: name -- The name of the experiment. (default=u'experiment') string -- A string containing the experiment definition. # (default=None) pool_folder -- A specific folder to be used for the file pool. # (default=None) experiment_path -- The path of the experiment file. (default=None) fullscreen -- Indicates whether the experiment should be # executed in fullscreen. (default=False) auto_response -- Indicates whether auto-response mode should be # enabled. (default=False) logfile -- The logfile path. (default=u'defaultlog.csv') subject_nr -- The subject number. (default=0) </DOC>""" global pool_folders self.items = {} self.running = False self.auto_response = auto_response self.plugin_folder = u'plugins' self.start_response_interval = None self.cleanup_functions = [] self.restart = False self.title = u'My Experiment' self.transparent_variables = u'no' self.bidi = u'no' # Set default variables self.start = u'experiment' # Sound parameters self.sound_freq = 48000 self.sound_sample_size = -16 # Negative values mean signed self.sound_channels = 2 self.sound_buf_size = 512 self.resources = {} # Backend parameters self.canvas_backend = u'xpyriment' self.keyboard_backend = u'legacy' self.mouse_backend = u'xpyriment' self.sampler_backend = u'legacy' self.synth_backend = u'legacy' # Save the date and time, and the version of OpenSesame self.datetime = time.strftime(u'%c').decode(self.encoding, u'ignore') self.opensesame_version = misc.version self.opensesame_codename = misc.codename # Display parameters self.width = 1024 self.height = 768 self.background = u'black' self.foreground = u'white' self.fullscreen = fullscreen # Font parameters self.font_size = 18 self.font_family = u'mono' self.font_italic = u'no' self.font_bold = u'no' self.font_underline = u'no' # Logfile parameters self._log = None self.logfile = logfile # This is some duplication of the option parser in qtopensesame, # but nevertheless keep it so we don't need qtopensesame self.debug = debug.enabled self._stack = debug.stack # Pool folder if pool_folder == None: # On some systems tempfile.mkdtemp() triggers a UnicodeDecodeError. # This is resolved by passing the dir explicitly as a Unicode # string. This fix has been adapted from: # - <http://bugs.python.org/issue1681974> self.pool_folder = tempfile.mkdtemp(suffix= \ u'.opensesame_pool', dir=tempfile.gettempdir().decode( \ encoding=misc.filesystem_encoding())) pool_folders.append(self.pool_folder) debug.msg(u'creating new pool folder') else: debug.msg(u'reusing existing pool folder') self.pool_folder = pool_folder debug.msg(u'pool folder is \'%s\'' % self.pool_folder) string = self.open(string) item.item.__init__(self, name, self, string) # Default subject info self.set_subject(subject_nr) # Restore experiment path if experiment_path != None: self.experiment_path = experiment_path
def __init__(self, name=u'experiment', string=None, pool_folder=None): """<DOC> Constructor. The experiment is created automatically be OpenSesame and # you will generally not need to create it yourself. Keyword arguments: name -- The name of the experiment. (default='experiment') string -- A string containing the experiment definition. # (default=None) pool_folder -- A specific folder to be used for the file pool. # (default=None) </DOC>""" global pool_folders self.items = {} self.running = False self.auto_response = False self.plugin_folder = u'plugins' self.start_response_interval = None self.cleanup_functions = [] self.restart = False self.experiment_path = None self.title = u'My Experiment' self.transparent_variables = u'no' # Set default variables self.coordinates = u'relative' # DEPRECATED self.compensation = 0 # DEPRECATED self.start = u'experiment' # Sound parameters self.sound_freq = 48000 self.sound_sample_size = -16 # Negative values mean signed self.sound_channels = 2 self.sound_buf_size = 512 self.resources = {} # Backend parameters self.canvas_backend = u'xpyriment' self.keyboard_backend = u'legacy' self.mouse_backend = u'xpyriment' self.sampler_backend = u'legacy' self.synth_backend = u'legacy' # Display parameters self.width = 1024 self.height = 768 self.background = u'black' self.foreground = u'white' self.fullscreen = False # Font parameters self.font_size = 18 self.font_family = u'mono' self.font_italic = u'no' self.font_bold = u'no' self.font_underline = u'no' # Logfile parameters self._log = None self.logfile = None # This is a dummy variable for backwards compatibility. The logfile # encoding is always utf-8, and this variable doesn't do anything. self.logfile_codec = u'utf-8' # DEPRECATED # Default subject info self.subject_nr = 0 self.subject_parity = u'even' # This is some duplication of the option parser in qtopensesame, # but nevertheless keep it so we don't need qtopensesame self.debug = debug.enabled self._stack = debug.stack # Pool folder if pool_folder == None: # On some systems tempfile.mkdtemp() triggers a UnicodeDecodeError. # This is resolved by passing the dir explicitly as a Unicode # string. This fix has been adapted from: # - <http://bugs.python.org/issue1681974> self.pool_folder = tempfile.mkdtemp(suffix= \ u'.opensesame_pool', dir=tempfile.gettempdir().decode( \ encoding=misc.filesystem_encoding())) pool_folders.append(self.pool_folder) debug.msg(u'creating new pool folder') else: debug.msg(u'reusing existing pool folder') self.pool_folder = pool_folder debug.msg(u'pool folder is \'%s\'' % self.pool_folder) string = self.open(string) item.item.__init__(self, name, self, string)
def get_logfile(self, quick=False, subject_nr=0): """ Gets the logfile for the current session, either by falling back to a default value ('quickrun.csv') or through a pop-up dialogue. Keyword arguments: quick -- Indicates whether we are quickrunning the experiment. (default=False) subject_nr -- Indicates the subject number, which is used to suggest a logfile. (default=0) Returns: A pathname for the logfile or None if no logfile was chosen (i.e. the dialogue was cancelled). """ remember_logfile = True if quick: logfile = os.path.join(cfg.default_logfile_folder, cfg.quick_run_logfile) try: open(logfile, u'w').close() except: import tempfile from libopensesame import misc debug.msg(u'Failed to open %s' % logfile) logfile = os.path.join(safe_decode(tempfile.gettempdir(), enc=misc.filesystem_encoding()), safe_decode( tempfile.gettempprefix(), enc=misc.filesystem_encoding())+u'quickrun.csv') debug.msg(u'Using temporary file %s' % logfile) remember_logfile = False else: # Suggested filename suggested_path = os.path.join(cfg.default_logfile_folder, u'subject-%d.csv' % subject_nr) # Get the data file csv_filter = u'Comma-separated values (*.csv)' logfile = QtWidgets.QFileDialog.getSaveFileName( \ self.main_window.ui.centralwidget, \ _(u"Choose location for logfile (press 'escape' for default location)"), \ suggested_path, filter=csv_filter) # In PyQt5, the QFileDialog.getOpenFileName returns a tuple instead of # a string, of which the first position contains the path. if isinstance(logfile,tuple): logfile = logfile[0] # An empty string indicates that the dialogue was cancelled, in # which case we fall back to a default location. if logfile == u'': logfile = os.path.join(cfg.default_logfile_folder, u'defaultlog.csv') # If a logfile was provided, but it did not have a proper extension, # we add a `.csv` extension. else: if os.path.splitext(logfile)[1].lower() not in \ self.valid_logfile_extensions: logfile += self.default_logfile_extension # If the logfile is not writable, inform the user and cancel. try: open(logfile, u'w').close() except: self.main_window.experiment.notify( \ _(u"The logfile '%s' is not writable. Please choose another location for the logfile.") \ % logfile) return None if remember_logfile: # Remember the logfile folder for the next run cfg.default_logfile_folder = os.path.dirname(logfile) return logfile
def get_logfile(self, quick=False, subject_nr=0): """ Gets the logfile for the current session, either by falling back to a default value ('quickrun.csv') or through a pop-up dialogue. Keyword arguments: quick -- Indicates whether we are quickrunning the experiment. (default=False) subject_nr -- Indicates the subject number, which is used to suggest a logfile. (default=0) Returns: A pathname for the logfile or None if no logfile was chosen (i.e. the dialogue was cancelled). """ remember_logfile = True if quick: logfile = os.path.join( config.get_config(u"default_logfile_folder"), config.get_config(u"quick_run_logfile") ) try: open(logfile, u"w").close() except: import tempfile from libopensesame import misc debug.msg(u"Failed to open %s" % logfile) logfile = os.path.join( tempfile.gettempdir().decode(misc.filesystem_encoding()), tempfile.gettempprefix().decode(misc.filesystem_encoding()) + u"quickrun.csv", ) debug.msg(u"Using temporary file %s" % logfile) remember_logfile = False else: # Suggested filename suggested_path = os.path.join(config.get_config(u"default_logfile_folder"), u"subject-%d.csv" % subject_nr) # Get the data file csv_filter = u"Comma-separated values (*.csv)" logfile = unicode( QtGui.QFileDialog.getSaveFileName( self.main_window.ui.centralwidget, _(u"Choose location for logfile (press 'escape' for default location)"), suggested_path, filter=csv_filter, ) ) # An empty string indicates that the dialogue was cancelled, in # which case we fall back to a default location. if logfile == u"": logfile = os.path.join(config.get_config("default_logfile_folder"), u"defaultlog.csv") # If a logfile was provided, but it did not have a proper extension, # we add a `.csv` extension. else: if os.path.splitext(logfile)[1].lower() not in self.valid_logfile_extensions: logfile += self.default_logfile_extension # If the logfile is not writable, inform the user and cancel. try: open(logfile, u"w").close() except: self.main_window.experiment.notify( _(u"The logfile '%s' is not writable. Please choose another location for the logfile.") % logfile ) return None if remember_logfile: # Remember the logfile folder for the next run config.set_config("default_logfile_folder", os.path.dirname(logfile)) return logfile