OctoPrint/SkeinPyPy/skeinforge_application/skeinforge_utilities/skeinforge_profile.py

416 lines
17 KiB
Python

"""
Profile is a script to set the craft types setting for the skeinforge chain.
Profile presents the user with a choice of the craft types in the profile_plugins folder. The chosen craft type is used to determine the craft type profile for the skeinforge chain. The default craft type is extrusion.
The setting is the selection. If you hit 'Save and Close' the selection will be saved, if you hit 'Cancel' the selection will not be saved.
To change the profile setting, in a shell in the profile folder type:
> python profile.py
"""
from __future__ import absolute_import
#Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
import __init__
from fabmetheus_utilities import archive
from fabmetheus_utilities import euclidean
from fabmetheus_utilities import gcodec
from fabmetheus_utilities import settings
import os
import shutil
__author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
__date__ = '$Date: 2008/21/04 $'
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
def addListsSetCraftProfile( craftSequence, defaultProfile, repository, fileNameHelp ):
"Set the craft profile repository."
settings.addListsToRepository(fileNameHelp, repository)
repository.craftSequenceLabel = settings.LabelDisplay().getFromName('Craft Sequence: ', repository )
craftToolStrings = []
for craftTool in craftSequence[ : - 1 ]:
craftToolStrings.append( settings.getEachWordCapitalized( craftTool ) + '->')
craftToolStrings.append( settings.getEachWordCapitalized( craftSequence[-1] ) )
for craftToolStringIndex in xrange( 0, len( craftToolStrings ), 5 ):
craftLine = ' '.join( craftToolStrings[ craftToolStringIndex : craftToolStringIndex + 5 ] )
settings.LabelDisplay().getFromName( craftLine, repository )
settings.LabelDisplay().getFromName('', repository )
repository.profileList = ProfileList().getFromName('Profile List:', repository )
repository.profileListbox = ProfileListboxSetting().getFromListSetting( repository.profileList, 'Profile Selection:', repository, defaultProfile )
repository.addListboxSelection = AddProfile().getFromProfileListboxSettingRepository( repository.profileListbox, repository )
repository.deleteListboxSelection = DeleteProfile().getFromProfileListboxSettingRepository( repository.profileListbox, repository )
directoryName = archive.getProfilesPath()
archive.makeDirectory(directoryName)
repository.windowPosition.value = '0+400'
def addListsToCraftTypeRepository(fileNameHelp, repository):
"Add the value to the lists."
settings.addListsToRepositoryByFunction(fileNameHelp, getProfileDirectory, repository)
dotsMinusOne = fileNameHelp.count('.') - 1
x = 0
xAddition = 400
for step in xrange(dotsMinusOne):
x += xAddition
xAddition /= 2
repository.windowPosition.value = '%s+0' % x
def cancelAll():
"Cancel all the dialogs."
for globalRepositoryDialogValue in settings.getGlobalRepositoryDialogValues():
globalRepositoryDialogValue.cancel()
def getCraftTypeName(subName=''):
"Get the craft type from the profile."
profileSettings = getReadProfileRepository()
craftTypeName = settings.getSelectedPluginName( profileSettings.craftRadios )
if subName == '':
return craftTypeName
return os.path.join( craftTypeName, subName )
def getCraftTypePluginModule( craftTypeName = ''):
"Get the craft type plugin module."
if craftTypeName == '':
craftTypeName = getCraftTypeName()
profilePluginsDirectoryPath = getPluginsDirectoryPath()
return archive.getModuleWithDirectoryPath( profilePluginsDirectoryPath, craftTypeName )
def getNewRepository():
'Get new repository.'
return ProfileRepository()
def getPluginFileNames():
"Get analyze plugin fileNames."
return archive.getPluginFileNamesFromDirectoryPath( getPluginsDirectoryPath() )
def getPluginsDirectoryPath():
"Get the plugins directory path."
return archive.getSkeinforgePluginsPath('profile_plugins')
def getProfileDirectory():
"Get the profile directory."
craftTypeName = getCraftTypeName()
return os.path.join( craftTypeName, getProfileName(craftTypeName) )
def getProfileName(craftTypeName):
"Get the profile name from the craft type name."
craftTypeSettings = getCraftTypePluginModule(craftTypeName).getNewRepository()
settings.getReadRepository(craftTypeSettings)
return craftTypeSettings.profileListbox.value
def getReadProfileRepository():
"Get the read profile repository."
return settings.getReadRepository( ProfileRepository() )
def updateProfileSaveListeners():
"Call the save function of all the update profile save listeners."
for globalProfileSaveListener in euclidean.getListTableElements( settings.globalProfileSaveListenerListTable ):
globalProfileSaveListener.save()
cancelAll()
class AddProfile:
"A class to add a profile."
def addSelection(self):
"Add the selection of a listbox setting."
entryText = self.entry.get()
if entryText == '':
print('To add to the profiles, enter the material name.')
return
self.profileListboxSetting.listSetting.setValueToFolders()
if entryText in self.profileListboxSetting.listSetting.value:
print('There is already a profile by the name of %s, so no profile will be added.' % entryText )
return
self.entry.delete( 0, settings.Tkinter.END )
craftTypeProfileDirectory = archive.getProfilesPath( self.profileListboxSetting.listSetting.craftTypeName )
destinationDirectory = os.path.join( craftTypeProfileDirectory, entryText )
shutil.copytree( self.profileListboxSetting.getSelectedFolder(), destinationDirectory )
self.profileListboxSetting.listSetting.setValueToFolders()
self.profileListboxSetting.value = entryText
self.profileListboxSetting.setStateToValue()
def addSelectionWithEvent(self, event):
"Add the selection of a listbox setting, given an event."
self.addSelection()
def addToDialog( self, gridPosition ):
"Add this to the dialog."
gridPosition.increment()
self.entry = settings.Tkinter.Entry( gridPosition.master )
self.entry.bind('<Return>', self.addSelectionWithEvent )
self.entry.grid( row = gridPosition.row, column = 1, columnspan = 3, sticky = settings.Tkinter.W )
self.addButton = settings.Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = 'Add Profile', command = self.addSelection )
self.addButton.grid( row = gridPosition.row, column = 0 )
def getFromProfileListboxSettingRepository( self, profileListboxSetting, repository ):
"Initialize."
self.profileListboxSetting = profileListboxSetting
self.repository = repository
repository.displayEntities.append(self)
return self
class DeleteProfile( AddProfile ):
"A class to delete the selection of a listbox profile."
def addToDialog( self, gridPosition ):
"Add this to the dialog."
gridPosition.increment()
self.deleteButton = settings.Tkinter.Button( gridPosition.master, activebackground = 'black', activeforeground = 'white', text = "Delete Profile", command = self.deleteSelection )
self.deleteButton.grid( row = gridPosition.row, column = 0 )
def deleteSelection(self):
"Delete the selection of a listbox setting."
DeleteProfileDialog( self.profileListboxSetting, settings.Tkinter.Tk() )
class DeleteProfileDialog:
"A dialog to delete a profile."
def __init__(self, profileListboxSetting, root):
"Display a delete dialog."
self.profileListboxSetting = profileListboxSetting
self.root = root
root.title('Delete Warning')
rowIndex = 0
self.label = settings.Tkinter.Label(self.root, text = 'Do you want to delete the profile?')
self.label.grid(row = rowIndex, column = 0, columnspan = 3, sticky = settings.Tkinter.W)
rowIndex += 1
columnIndex = 1
deleteButton = settings.Tkinter.Button(root, activebackground = 'black', activeforeground = 'red', command = self.delete, fg = 'red', text = 'Delete')
deleteButton.grid(row = rowIndex, column = columnIndex)
columnIndex += 1
noButton = settings.Tkinter.Button(root, activebackground = 'black', activeforeground = 'darkgreen', command = self.no, fg = 'darkgreen', text = 'Do Nothing')
noButton.grid(row = rowIndex, column = columnIndex)
def delete(self):
"Delete the selection of a listbox setting."
self.profileListboxSetting.setToDisplay()
self.profileListboxSetting.listSetting.setValueToFolders()
if self.profileListboxSetting.value not in self.profileListboxSetting.listSetting.value:
return
lastSelectionIndex = 0
currentSelectionTuple = self.profileListboxSetting.listbox.curselection()
if len(currentSelectionTuple) > 0:
lastSelectionIndex = int(currentSelectionTuple[0])
else:
print('No profile is selected, so no profile will be deleted.')
return
craftTypeName = self.profileListboxSetting.listSetting.craftTypeName
settings.deleteDirectory(archive.getProfilesPath(craftTypeName), self.profileListboxSetting.value)
settings.deleteDirectory(settings.getProfilesDirectoryInAboveDirectory(craftTypeName), self.profileListboxSetting.value)
self.profileListboxSetting.listSetting.setValueToFolders()
if len(self.profileListboxSetting.listSetting.value) < 1:
defaultSettingsDirectory = archive.getProfilesPath(os.path.join(craftTypeName, self.profileListboxSetting.defaultValue))
archive.makeDirectory(defaultSettingsDirectory)
self.profileListboxSetting.listSetting.setValueToFolders()
lastSelectionIndex = min(lastSelectionIndex, len(self.profileListboxSetting.listSetting.value) - 1)
self.profileListboxSetting.value = self.profileListboxSetting.listSetting.value[lastSelectionIndex]
self.profileListboxSetting.setStateToValue()
self.no()
def no(self):
"The dialog was closed."
self.root.destroy()
class ProfileList:
"A class to list the profiles."
def getFromName( self, name, repository ):
"Initialize."
self.craftTypeName = repository.lowerName
self.name = name
self.repository = repository
self.setValueToFolders()
return self
def setValueToFolders(self):
"Set the value to the folders in the profiles directories."
self.value = settings.getFolders( archive.getProfilesPath( self.craftTypeName ) )
defaultFolders = settings.getFolders( settings.getProfilesDirectoryInAboveDirectory( self.craftTypeName ) )
for defaultFolder in defaultFolders:
if defaultFolder not in self.value:
self.value.append( defaultFolder )
self.value.sort()
class ProfileListboxSetting( settings.StringSetting ):
"A class to handle the profile listbox."
def addToDialog( self, gridPosition ):
"Add this to the dialog."
#http://www.pythonware.com/library/tkinter/introduction/x5453-patterns.htm
self.root = gridPosition.master
gridPosition.increment()
from fabmetheus_utilities.hidden_scrollbar import HiddenScrollbar
scrollbar = HiddenScrollbar( gridPosition.master )
self.listbox = settings.Tkinter.Listbox( gridPosition.master, selectmode = settings.Tkinter.SINGLE, yscrollcommand = scrollbar.set )
self.listbox.bind('<ButtonRelease-1>', self.buttonReleaseOne )
gridPosition.master.bind('<FocusIn>', self.focusIn )
scrollbar.config( command = self.listbox.yview )
self.listbox.grid( row = gridPosition.row, column = 0, sticky = settings.Tkinter.N + settings.Tkinter.S )
scrollbar.grid( row = gridPosition.row, column = 1, sticky = settings.Tkinter.N + settings.Tkinter.S )
self.setStateToValue()
self.repository.saveListenerTable['updateProfileSaveListeners'] = updateProfileSaveListeners
def buttonReleaseOne(self, event):
"Button one released."
self.setValueToIndex( self.listbox.nearest(event.y) )
def focusIn(self, event):
"The root has gained focus."
settings.getReadRepository(self.repository)
self.setStateToValue()
def getFromListSetting( self, listSetting, name, repository, value ):
"Initialize."
self.getFromValueOnly( name, repository, value )
self.listSetting = listSetting
repository.displayEntities.append(self)
repository.preferences.append(self)
return self
def getSelectedFolder(self):
"Get the selected folder."
settingProfileSubfolder = settings.getSubfolderWithBasename( self.value, archive.getProfilesPath( self.listSetting.craftTypeName ) )
if settingProfileSubfolder != None:
return settingProfileSubfolder
toolProfileSubfolder = settings.getSubfolderWithBasename( self.value, settings.getProfilesDirectoryInAboveDirectory( self.listSetting.craftTypeName ) )
return toolProfileSubfolder
def setStateToValue(self):
"Set the listbox items to the list setting."
self.listbox.delete( 0, settings.Tkinter.END )
for item in self.listSetting.value:
self.listbox.insert( settings.Tkinter.END, item )
if self.value == item:
self.listbox.select_set( settings.Tkinter.END )
def setToDisplay(self):
"Set the selection value to the listbox selection."
currentSelectionTuple = self.listbox.curselection()
if len( currentSelectionTuple ) > 0:
self.setValueToIndex( int( currentSelectionTuple[0] ) )
def setValueToIndex( self, index ):
"Set the selection value to the index."
valueString = self.listbox.get( index )
self.setValueToString( valueString )
def setValueToString( self, valueString ):
"Set the value to the value string."
self.value = valueString
if self.getSelectedFolder() == None:
self.value = self.defaultValue
if self.getSelectedFolder() == None:
if len( self.listSetting.value ) > 0:
self.value = self.listSetting.value[0]
class ProfilePluginRadioButtonsSaveListener:
"A class to update the profile radio buttons."
def addToDialog( self, gridPosition ):
"Add this to the dialog."
euclidean.addElementToListDictionaryIfNotThere( self, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable )
def getFromRadioPlugins( self, radioPlugins, repository ):
"Initialize."
self.name = 'ProfilePluginRadioButtonsSaveListener'
self.radioPlugins = radioPlugins
self.repository = repository
repository.displayEntities.append(self)
return self
def save(self):
"Profile has been saved and profile radio plugins should be updated."
craftTypeName = getCraftTypeName()
for radioPlugin in self.radioPlugins:
if radioPlugin.name == craftTypeName:
if radioPlugin.setSelect():
self.repository.pluginFrame.update()
return
class ProfileRepository:
"A class to handle the profile entities."
def __init__(self):
"Set the default entities, execute title & repository fileName."
settings.addListsToRepository('skeinforge_application.skeinforge_utilities.skeinforge_profile.html', self)
importantFileNames = ['extrusion']
self.craftRadios = settings.getRadioPluginsAddPluginFrame( getPluginsDirectoryPath(), importantFileNames, getPluginFileNames(), self )
ProfilePluginRadioButtonsSaveListener().getFromRadioPlugins( self.craftRadios, self )
for craftRadio in self.craftRadios:
craftRadio.updateFunction = self.updateRelay
directoryName = archive.getProfilesPath()
archive.makeDirectory(directoryName)
self.windowPosition.value = '0+200'
def updateRelay(self):
"Update the plugin frame then the ProfileSaveListeners."
self.pluginFrame.update()
updateProfileSaveListeners()
class ProfileSelectionMenuRadio:
"A class to display a profile selection menu radio button."
def addToDialog( self, gridPosition ):
"Add this to the dialog."
self.activate = False
self.menuButtonDisplay.setToNameAddToDialog( self.valueName, gridPosition )
self.menuButtonDisplay.menu.add_radiobutton( label = self.valueName, command = self.clickRadio, value = self.valueName, variable = self.menuButtonDisplay.radioVar )
self.menuLength = self.menuButtonDisplay.menu.index( settings.Tkinter.END )
if self.value:
self.menuButtonDisplay.radioVar.set( self.valueName )
self.menuButtonDisplay.menu.invoke( self.menuLength )
euclidean.addElementToListDictionaryIfNotThere( self.repository, self.repository.repositoryDialog, settings.globalProfileSaveListenerListTable )
self.activate = True
def clickRadio(self):
"Workaround for Tkinter bug, invoke and set the value when clicked."
if not self.activate:
return
settings.saveAll()
self.menuButtonDisplay.radioVar.set( self.valueName )
pluginModule = getCraftTypePluginModule()
profilePluginSettings = settings.getReadRepository( pluginModule.getNewRepository() )
profilePluginSettings.profileListbox.value = self.name
settings.writeSettings( profilePluginSettings )
updateProfileSaveListeners()
def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ):
"Initialize."
self.setToMenuButtonDisplay( menuButtonDisplay, name, repository, value )
self.valueName = name.replace('_', ' ')
return self
def setToMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ):
"Initialize."
self.menuButtonDisplay = menuButtonDisplay
self.menuButtonDisplay.menuRadios.append(self)
self.name = name
self.repository = repository
self.value = value
repository.displayEntities.append(self)
class ProfileTypeMenuRadio( ProfileSelectionMenuRadio ):
"A class to display a profile type menu radio button."
def clickRadio(self):
"Workaround for Tkinter bug, invoke and set the value when clicked."
if not self.activate:
return
settings.saveAll()
self.menuButtonDisplay.radioVar.set( self.valueName )
profileSettings = getReadProfileRepository()
plugins = profileSettings.craftRadios
for plugin in plugins:
plugin.value = ( plugin.name == self.name )
settings.writeSettings( profileSettings )
updateProfileSaveListeners()
def getFromMenuButtonDisplay( self, menuButtonDisplay, name, repository, value ):
"Initialize."
self.setToMenuButtonDisplay( menuButtonDisplay, name, repository, value )
self.valueName = settings.getEachWordCapitalized( name )
return self