Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature renameRoutine #1136

Merged
merged 8 commits into from Mar 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion psychopy/__init__.py
Expand Up @@ -44,4 +44,4 @@
for pathName in prefs.general['paths']:
sys.path.append(pathName)

from psychopy.tools.versionchooser import useVersion
from psychopy.tools.versionchooser import useVersion
44 changes: 41 additions & 3 deletions psychopy/app/builder/builder.py
Expand Up @@ -433,7 +433,7 @@ def drawComponent(self, dc, component, yPos):
# deduce start and stop times if possible
startTime, duration, nonSlipSafe = component.getStartAndDuration()
# draw entries on timeline (if they have some time definition)
if startTime != None and duration != None:
if startTime is not None and duration is not None:
# then we can draw a sensible time bar!
xScale = self.getSecsPerPixel()
dc.SetPen(wx.Pen(wx.Colour(200, 100, 100, 0),
Expand Down Expand Up @@ -532,6 +532,10 @@ def addRoutinePage(self, routineName, routine):
routinePage = RoutineCanvas(notebook=self, routine=routine)
self.AddPage(routinePage, routineName)

def renameRoutinePage(self, index, newName,):

self.SetPageText(index, newName)

def removePages(self):
for ii in range(self.GetPageCount()):
currId = self.GetSelection()
Expand Down Expand Up @@ -1002,7 +1006,7 @@ def __init__(self, parent, id=-1, title='PsychoPy (Experiment Builder)',
parent=self, app=self.app, size=(700, 300))

# setup a default exp
if fileName != None and os.path.isfile(fileName):
if fileName is not None and os.path.isfile(fileName):
self.fileOpen(filename=fileName, closeCurrent=False)
else:
self.lastSavedCopy = None
Expand Down Expand Up @@ -1077,7 +1081,7 @@ def makeToolbar(self):
compileBmp = wx.Bitmap(join(rc, 'compile%i.png' % tbSize), PNG)
settingsBmp = wx.Bitmap(join(rc, 'settingsExp%i.png' % tbSize), PNG)
preferencesBmp = wx.Bitmap(join(rc, 'preferences%i.png' % tbSize),
PNG)
PNG)
monitorsBmp = wx.Bitmap(join(rc, 'monitors%i.png' % tbSize), PNG)

ctrlKey = 'Ctrl+' # OS-dependent tool-tips
Expand Down Expand Up @@ -1309,6 +1313,10 @@ def makeMenus(self):
"experiment"),
wx.ITEM_NORMAL)
wx.EVT_MENU(self, self.IDs.pasteRoutine, self.onPasteRoutine)
menu.Append(self.IDs.renameRoutine,
_translate("&Rename Routine\t%s") % keys['renameRoutine'],
_translate("Change the name of this routine"))
wx.EVT_MENU(self, self.IDs.renameRoutine, self.renameRoutine)
menu.AppendSeparator()

menu.Append(self.IDs.addRoutineToFlow,
Expand Down Expand Up @@ -2003,7 +2011,37 @@ def setExperimentSettings(self, event=None):
def addRoutine(self, event=None):
self.routinePanel.createNewRoutine()

def renameRoutine(self, name, event=None, returnName=True):
# get notebook details
currentRoutine = self.routinePanel.getCurrentPage()
currentRoutineIndex = self.routinePanel.GetPageIndex(currentRoutine)
routine = self.routinePanel.GetPage(
self.routinePanel.GetSelection()).routine
oldName = routine.name
msg = _translate("What is the new name for the Routine?")
dlg = wx.TextEntryDialog(self, message=msg,
caption=_translate('Rename'))
exp = self.exp
if dlg.ShowModal() == wx.ID_OK:
name = dlg.GetValue()
# silently auto-adjust the name to be valid, and register in the
# namespace:
name = exp.namespace.makeValid(
name, prefix='routine')
if oldName in self.exp.routines.keys():
# Swap old with new names
self.exp.routines[oldName].name = name
self.exp.routines[name] = self.exp.routines.pop(oldName)
for comp in self.exp.routines[name]:
comp.parentName = name
self.exp.namespace.rename(oldName, name)
self.routinePanel.renameRoutinePage(currentRoutineIndex, name)
self.addToUndoStack("`RENAME Routine `%s`" % oldName)
dlg.Destroy()
self.flowPanel.draw()

def generateScript(self, experimentPath):
self.app.prefs.app['debugMode'] = "debugMode"
if self.app.prefs.app['debugMode']:
return self.exp.writeScript(expPath=experimentPath)
# getting the track-back is very helpful when debugging the app
Expand Down
24 changes: 18 additions & 6 deletions psychopy/app/builder/experiment.py
Expand Up @@ -163,7 +163,7 @@ def requirePsychopyLibs(self, libs=()):
"""Add a list of top-level psychopy libs that the experiment
will need. e.g. [visual, event]
"""
if type(libs) != list:
if not isinstance(libs, list):
libs = list(libs)
for lib in libs:
if lib not in self.psychopyLibs:
Expand All @@ -181,6 +181,7 @@ def addRoutine(self, routineName, routine=None):
else:
self.routines[routineName] = routine

#
def writeScript(self, expPath=None):
"""Write a PsychoPy script for the experiment
"""
Expand Down Expand Up @@ -1344,7 +1345,7 @@ def _dubiousConstantUpdates(self, component):
not isinstance(field.val, basestring)):
continue # continue == no problem, no warning
if not (field.allowedUpdates and
type(field.allowedUpdates) == list and
isinstance(field.allowedUpdates, list) and
len(field.allowedUpdates) and
field.updates == 'constant'):
continue
Expand Down Expand Up @@ -1374,7 +1375,7 @@ def _prescreenValues(self):
constWarnings = []
for entry in self:
# NB each entry is a routine or LoopInitiator/Terminator
if type(entry) != Routine:
if not isinstance(entry, Routine):
continue
for component in entry:
# detect and strip trailing whitespace (can cause problems):
Expand All @@ -1385,7 +1386,7 @@ def _prescreenValues(self):
if (field.label.lower() == 'text' or
not field.valType in ('str', 'code')):
continue
if (type(field.val) == basestring and
if (isinstance(field.val, basestring) and
field.val != field.val.strip()):
trailingWhitespace.append(
(field.val, key, component, entry))
Expand Down Expand Up @@ -1910,7 +1911,7 @@ def add(self, name, sublist='default'):
return
if sublist == 'default':
sublist = self.user
if type(name) != list:
if not isinstance(name, list):
sublist.append(name)
else:
sublist += name
Expand All @@ -1923,12 +1924,23 @@ def remove(self, name, sublist='default'):
return
if sublist == 'default':
sublist = self.user
if type(name) != list:
if not isinstance(name, list):
name = [name]
for n in list(name):
if n in sublist:
del sublist[sublist.index(n)]

def rename(self, name, newName, sublist='default'):
if name is None:
return
if sublist == 'default':
sublist = self.user
if not isinstance(name, list):
name = [name]
for n in list(name):
if n in sublist:
sublist[sublist.index(n)] = newName

def makeValid(self, name, prefix='var'):
"""given a string, return a valid and unique variable name.
replace bad characters with underscore, add an integer suffix until
Expand Down
44 changes: 30 additions & 14 deletions psychopy/app/builder/flow.py
Expand Up @@ -86,8 +86,10 @@ def __init__(self, frame, id=-1):
# for the context menu use the ID of the drawn icon to retrieve
# the component (loop or routine)
self.componentFromID = {}
self.contextMenuLabels = {'remove': _translate('remove')}
self.contextMenuItems = ['remove']
self.contextMenuLabels = {
'remove': _translate('remove'),
'rename': _translate('rename')}
self.contextMenuItems = ['remove', 'rename']
self.contextItemFromID = {}
self.contextIDFromItem = {}
for item in self.contextMenuItems:
Expand Down Expand Up @@ -441,13 +443,31 @@ def getGapPointsCrossingStreams(self, gapPoint):

def showContextMenu(self, component, xy):
menu = wx.Menu()
for item in self.contextMenuItems:
id = self.contextIDFromItem[item]
menu.Append(id, self.contextMenuLabels[item])
wx.EVT_MENU(menu, id, self.onContextSelect)
self.frame.PopupMenu(menu, xy)
# destroy to avoid mem leak:
menu.Destroy()
# get ID
# the ID is also the index to the element in the flow list
compID = self._menuComponentID
flow = self.frame.exp.flow
component = flow[compID]
compType = component.getType()
print (compType)
if compType == 'Routine':
for item in (self.contextMenuItems):
id = self.contextIDFromItem[item]
menu.Append(id, self.contextMenuLabels[item])
wx.EVT_MENU(menu, id, self.onContextSelect)
self.frame.PopupMenu(menu, xy)
# destroy to avoid mem leak:
menu.Destroy()
else:
for item in (self.contextMenuItems):
if item == 'rename':
continue
id = self.contextIDFromItem[item]
menu.Append(id, self.contextMenuLabels[item])
wx.EVT_MENU(menu, id, self.onContextSelect)
self.frame.PopupMenu(menu, xy)
# destroy to avoid mem leak:
menu.Destroy()

def onContextSelect(self, event):
"""Perform a given action on the component chosen
Expand All @@ -466,11 +486,7 @@ def onContextSelect(self, event):
self.frame.addToUndoStack(
"REMOVE `%s` from Flow" % component.params['name'])
if op == 'rename':
print('rename is not implemented yet')
# if component is a loop: DlgLoopProperties
# elif component is a routine: DlgRoutineProperties
self.draw()
self._menuComponentID = None
self.frame.renameRoutine(component)

def removeComponent(self, component, compID):
"""Remove either a Routine or a Loop from the Flow
Expand Down
1 change: 1 addition & 0 deletions psychopy/app/preferencesDlg.py
Expand Up @@ -98,6 +98,7 @@
'newRoutine': _translate('new Routine'),
'copyRoutine': _translate('copy Routine'),
'pasteRoutine': _translate('paste Routine'),
'renameRoutine': _translate('rename Routine')
'toggleOutputPanel': _translate('toggle output panel'),
'switchToBuilder': _translate('switch to Builder'),
'switchToCoder': _translate('switch to Coder'),
Expand Down
1 change: 1 addition & 0 deletions psychopy/app/wxIDs.py
Expand Up @@ -24,6 +24,7 @@
remLoopFromFlow = wx.NewId()
copyRoutine = wx.NewId()
pasteRoutine = wx.NewId()
renameRoutine = wx.NewId()

# view menu
openCoderView = wx.NewId()
Expand Down
5 changes: 4 additions & 1 deletion psychopy/preferences/Darwin.spec
Expand Up @@ -2,7 +2,8 @@
# This file specifies defaults for psychopy prefs for Darwin.

# !! This file is auto-generated and will be overwritten!!
# Edit baseNoArch.spec (all platforms) or generateSpec.py (platform-specific) instead.
# Edit baseNoArch.spec (all platforms) or generateSpec.py
# (platform-specific) instead.

# Notes on usage for developers (not needed or intended for use when making or running experiments):
# - baseNoArch.spec is copied & edited to be platform specific when you run generateSpec.py
Expand Down Expand Up @@ -194,6 +195,8 @@
pasteRoutine = string(default='Ctrl+Shift+V')
# Coder: show / hide the output panel
toggleOutputPanel = string(default='Ctrl+Shift+O')
#Builder: rename an existing routine
renameRoutine = string(default='Ctrl+Shift+R')
# switch to Builder window from Coder
switchToBuilder = string(default='Ctrl+L')
# switch to Coder window from Builder
Expand Down
5 changes: 4 additions & 1 deletion psychopy/preferences/FreeBSD.spec
Expand Up @@ -2,7 +2,8 @@
# This file specifies defaults for psychopy prefs for FreeBSD.

# !! This file is auto-generated and will be overwritten!!
# Edit baseNoArch.spec (all platforms) or generateSpec.py (platform-specific) instead.
# Edit baseNoArch.spec (all platforms) or generateSpec.py
# (platform-specific) instead.

# Notes on usage for developers (not needed or intended for use when making or running experiments):
# - baseNoArch.spec is copied & edited to be platform specific when you run generateSpec.py
Expand Down Expand Up @@ -194,6 +195,8 @@
pasteRoutine = string(default='Ctrl+Shift+V')
# Coder: show / hide the output panel
toggleOutputPanel = string(default='Ctrl+Shift+O')
#Builder: rename an existing routine
renameRoutine = string(default='Ctrl+Shift+R')
# switch to Builder window from Coder
switchToBuilder = string(default='Ctrl+L')
# switch to Coder window from Builder
Expand Down
5 changes: 4 additions & 1 deletion psychopy/preferences/Linux.spec
Expand Up @@ -2,7 +2,8 @@
# This file specifies defaults for psychopy prefs for Linux.

# !! This file is auto-generated and will be overwritten!!
# Edit baseNoArch.spec (all platforms) or generateSpec.py (platform-specific) instead.
# Edit baseNoArch.spec (all platforms) or generateSpec.py
# (platform-specific) instead.

# Notes on usage for developers (not needed or intended for use when making or running experiments):
# - baseNoArch.spec is copied & edited to be platform specific when you run generateSpec.py
Expand Down Expand Up @@ -194,6 +195,8 @@
pasteRoutine = string(default='Ctrl+Shift+V')
# Coder: show / hide the output panel
toggleOutputPanel = string(default='Ctrl+Shift+O')
#Builder: rename an existing routine
renameRoutine = string(default='Ctrl+Shift+R')
# switch to Builder window from Coder
switchToBuilder = string(default='Ctrl+L')
# switch to Coder window from Builder
Expand Down
5 changes: 4 additions & 1 deletion psychopy/preferences/Windows.spec
Expand Up @@ -2,7 +2,8 @@
# This file specifies defaults for psychopy prefs for Windows.

# !! This file is auto-generated and will be overwritten!!
# Edit baseNoArch.spec (all platforms) or generateSpec.py (platform-specific) instead.
# Edit baseNoArch.spec (all platforms) or generateSpec.py
# (platform-specific) instead.

# Notes on usage for developers (not needed or intended for use when making or running experiments):
# - baseNoArch.spec is copied & edited to be platform specific when you run generateSpec.py
Expand Down Expand Up @@ -194,6 +195,8 @@
pasteRoutine = string(default='Ctrl+Shift+V')
# Coder: show / hide the output panel
toggleOutputPanel = string(default='Ctrl+Shift+O')
#Builder: rename an existing routine
renameRoutine = string(default='Ctrl+Shift+R')
# switch to Builder window from Coder
switchToBuilder = string(default='Ctrl+L')
# switch to Coder window from Builder
Expand Down
2 changes: 2 additions & 0 deletions psychopy/preferences/baseNoArch.spec
Expand Up @@ -191,6 +191,8 @@
pasteRoutine = string(default='Ctrl+Shift+V')
# Coder: show / hide the output panel
toggleOutputPanel = string(default='Ctrl+Shift+O')
#Builder: rename an existing routine
renameRoutine = string(default='Ctrl+Shift+R')
# switch to Builder window from Coder
switchToBuilder = string(default='Ctrl+L')
# switch to Coder window from Builder
Expand Down