import time;
import ghs_window;
from ghs_util import *;

# The workspace tree should only be generated by "GetWorkspaceInformation()"
# in "GHS_LauncherWindow()", and the tree should be read-only. Changing to
# the tree will have no affect to the actual workspace kept in MULTI Launcher.
class GHS_Action(object):
    """ Describe MULTI Launcher's Action. """
    #
    # GHS: Validated (internal use only)
    #
    def __init__(self, acName, acArgs, enabled=True):
	self.name = acName;
	self.args = acArgs;
	self.enabled = enabled;
	self.parent = None;

    #
    # Dump the action's information.
    #
    # GHS: Validated
    #
    def DumpTree(self, treeLine=False):
	indUnit = "  ";
	if treeLine:
	    cn = len(self.parent.actions);
	    if self.parent.actions[cn-1] == self:
		indStr = indUnit+"|_" ;
	    else:
		indStr = indUnit+"| ";
	else:
	    indStr = indUnit*2;
	if self.enabled:
	    print("%s%s\t%s" % (indStr, self.name, self.args));
	else:
	    print("%s%s\t%s\t(disabled)" % (indStr, self.name, self.args));

	return True;
    # aliases for the function
    dumptree = DumpTree;
    Dump = DumpTree;
    dump = DumpTree;


class GHS_ActionSequence(object):
    """ Describe MULTI Launcher's Action Sequence. """
    #
    # GHS: Validated (internal use only)
    #
    def __init__(self, asName):
	self.name = asName;
	self.actions = [];
	self.parent = None;

    #
    # Append a node to the current node's children list.
    #
    # GHS: Validated (internal use only)
    #
    def AddChild(self, action):
	if not isinstance(action, GHS_Action):
	    print("Expect GHS_Action node in GHS_ActionSequence.AddChild()");
	    return False;
	self.actions.append(action);
	action.parent = (self);
	return True;
    # aliases for the function
    addchild = AddChild;

    #
    # Dump the action sequence's information.
    #
    # GHS: Validated
    #
    def DumpTree(self, treeLine=True):
	indUnit = "  ";
	print("%s%s" % (indUnit, self.name));
	for action in self.actions:
	    action.Dump(treeLine);

	return True;
    # aliases for the function
    dumptree = DumpTree;
    Dump = DumpTree;
    dump = DumpTree;

    #
    # Search action in Action Sequence
    #
    # Here is about column:
    #     column 0 means the action name
    #     column 1 means the action argument
    # column -1 means for both of them.
    #
    # If "all" is True, a list of action objects satisfying the criteria
    # or an empty list will be returned.
    # If "all" is False, the fist action object satisfying the criteria
    # or None will be returned.
    #
    # GHS: Validated
    #
    def Search(self, value, column=-1, match=False, all=False):
	if all:
	    ret = [];
	else:
	    ret = None;
	for action in self.actions:
	    good = False;
	    if column <= 0:
		if value == action.name:
		    good = True;
		elif match and re.match(value, action.name):
		    good = True;
		elif not match and re.search(value, action.name):
		    good = True;
	    if not good and (column < 0 or column == 1):
		if value == action.args:
		    good = True;
		elif match and re.match(value, action.args):
		    good = True;
		elif not match and re.search(value, action.args):
		    good = True;

	    if good:
		if all:
		    ret.append(action);
		else:
		    return action;

	return ret;
    # aliases for the function
    search = Search;


class GHS_Variable(object):
    """ Describe MULTI Launcher's  Variable. """
    #
    # GHS: Validated (internal use only)
    #
    def __init__(self, varName, varValue, varType):
	self.name = varName;
	self.value = varValue;
	# Only useful for dumping.
	self.type = varType;
	self.parent = None;

    #
    # Dump the variable's information.
    #
    # GHS: Validated
    #
    def DumpTree(self, treeLine=False):
	if treeLine:
	    if self.type == GHS_Workspace.localVarType:
		varList = self.parent.localVariables;
	    elif self.type == GHS_Workspace.globalVarType:
		varList = self.parent.globalVariables;
	    elif self.type == GHS_Workspace.predefinedVarType:
		varList = self.parent.predefinedVariables;
	    else:
		print("  %s\t-> %s" % (self.name, self.value));
		return True;

	    indStr = "";
	    cn = len(varList);
	    if varList[cn-1] == self:
		indStr = "|_" + indStr;
	    else:
		indStr = "| " + indStr;
	else:
	    indStr = "  ";
	print("%s%s\t-> %s" % (indStr, self.name, self.value));

	return True;
    # aliases for the function
    dumptree = DumpTree;
    Dump = DumpTree;
    dump = DumpTree;


class GHS_Workspace(object):
    """ Describe MULTI Launcher's Workspace. """
    localVarType = "local";
    globalVarType = "global";
    predefinedVarType = "predefined";

    dumpNameMask = 0x1;
    dumpWorkingDirMask = 0x2;
    dumpLocalVarsMask = 0x4;
    dumpGlobalVarsMask = 0x8;
    dumpPredefinedVarsMask = 0x10;
    dumpActionsMask = 0x20;

    #
    # GHS: Validated (internal use only)
    #
    def __init__(self, wsName):
	self.name = wsName;
	self.workingDir = "";
	self.localVariables = [];
	self.globalVariables = [];
	self.predefinedVariables = [];
	self.actionSequences = [];

    #
    # Append a node to the current node's children list.
    #
    # GHS: Validated (internal use only)
    #
    def AddVariable(self, var):
	if var.type == GHS_Workspace.localVarType:
	    varList = self.localVariables;
	elif var.type == GHS_Workspace.globalVarType:
	    varList = self.globalVariables;
	elif var.type == GHS_Workspace.predefinedVarType:
	    varList = self.predefinedVariables;
	else:
	    print("Unknown variable type '%s'" % (var.type));
	    return False;

	varList.append(var);
	var.parent = self;
	return True;
    # aliases for the function
    addvariable = AddVariable;

    #
    # Dump the workspace's information.
    #
    # "mask" argument cntrols what elements are to be dumped. By default,
    # the workspace's all elements are dumped.
    #
    # GHS: Validated
    #
    def DumpTree(self, treeLine=True, mask=0xff):
	if (mask & GHS_Workspace.dumpNameMask) != 0:
	    print("Name: %s" % self.name);
	if (mask & GHS_Workspace.dumpWorkingDirMask) != 0:
	    print("Working Dir: %s" % self.workingDir);

	if (mask & GHS_Workspace.dumpLocalVarsMask) != 0 and len(self.localVariables) > 0:
	    print("Local Variables:");
	    for var in self.localVariables:
		var.Dump(False);
	if (mask & GHS_Workspace.dumpGlobalVarsMask) != 0 and len(self.globalVariables) > 0:
	    print("Global Variables:");
	    for var in self.globalVariables:
		var.Dump(False);
	if (mask & GHS_Workspace.dumpPredefinedVarsMask) != 0 and len(self.predefinedVariables) > 0:
	    print("Pre-defined Variables:");
	    for var in self.predefinedVariables:
		var.Dump(False);

	if (mask & GHS_Workspace.dumpActionsMask) != 0 and len(self.actionSequences) > 0:
	    print("Actions:");
	    for act in self.actionSequences:
		act.Dump(treeLine);
    # aliases for the function
    dumptree = DumpTree;
    Dump = DumpTree;
    dump = DumpTree;
	

    #
    # Search action sequence in workspace.
    #
    # "asName" can be regular expression.
    #
    # "match" is True to indicate to use Python's regular expression's "match"
    # method to check the given action sequence name value, otherwise, use
    # Python's regular expression's "search" method to check.
    #
    # If "all" is True, a list of action sequence objects satisfying the 
    # criteria or an empty list will be returned.
    # If "all" is False, the fist action sequence object satisfying the 
    # criteria or None will be returned.
    #
    # GHS: Validated
    #
    def SearchActionSequence(self, asName, match=False, all=False):
	if all:
	    ret = [];
	else:
	    ret = None;
	for item in self.actionSequences:
	    good = False;
	    if item.name == asName:
		good = True;
	    elif match and re.match(asName, item.name):
		good = True;
	    elif not match and re.search(asName, item.name):
		good = True;
	    if good:
		if all:
		    ret.append(item);
		else:
		    return item;
	return ret;
    # aliases for the function
    searchactionsequence = SearchActionSequence;
    SearchActionSeq = SearchActionSequence;
    searchactionseq = SearchActionSequence;

    #
    # Search action in workspace.
    #
    # If asName is "", all Action Sequences are searched.
    #
    # Here is about column:
    #     column 0 means the action name
    #     column 1 means the action argument
    # column -1 means for both of them.
    #
    # If "all" is True, a list of action objects satisfying the criteria
    # or an empty list will be returned.
    # If "all" is False, the fist action object satisfying the criteria
    # or None will be returned.
    #
    # GHS: Validated
    #
    def SearchAction(self, asName, value, column=-1, match=False, all=False):
	if asName:
	    asList = self.SearchActionSequence(asName, match, True);
	else:
	    asList = self.actionSequences;
	if all:
	    ret = [];
	else:
	    ret = None;
	for asItem in asList:
	    res = asItem.Search(value, column, match, all);
	    if all:
		ret = ret + res;
	    elif res:
		return res;

	return ret;
    # aliases for the function
    searchaction = SearchAction;


    #
    # Search variable in workspace.
    #
    # If varType is "", all kinds of variables are searched, otherwise, only
    # the specified kind variables will be searched:
    #	local
    #	global
    #	predefined
    #
    # Here is about column:
    #     column 0 means the variable name
    #     column 1 means the variable value
    # column -1 means for both of them.
    #
    # If "all" is True, a list of action objects satisfying the criteria
    # or an empty list will be returned.
    # If "all" is False, the fist action object satisfying the criteria
    # or None will be returned.
    #
    # GHS: Validated
    #
    def SearchVariable(self, varType, value, column=-1, match=False, all=False):
	if all:
	    ret = [];
	else:
	    ret = None;

	if not varType or varType == GHS_Workspace.localVarType:
	    for varItem in self.localVariables:
		good = False;
		if column <= 0:
		    if value == varItem.name:
			good = True;
		    elif match and re.match(value, varItem.name):
			good = True;
		    elif not match and re.search(value, varItem.name):
			good = True;
		if not good and (column < 0 or column == 1):
		    if value == varItem.value:
			good = True;
		    elif match and re.match(value, varItem.value):
			good = True;
		    elif not match and re.search(value, varItem.value):
			good = True;
    
		if good:
		    if all:
			ret.append(varItem);
		    else:
			return varItem;

	if not varType or varType == GHS_Workspace.globalVarType:
	    for varItem in self.globalVariables:
		good = False;
		if column <= 0:
		    if value == varItem.name:
			good = True;
		    elif match and re.match(value, varItem.name):
			good = True;
		    elif not match and re.search(value, varItem.name):
			good = True;
		if not good and (column < 0 or column == 1):
		    if value == varItem.value:
			good = True;
		    elif match and re.match(value, varItem.value):
			good = True;
		    elif not match and re.search(value, varItem.value):
			good = True;
    
		if good:
		    if all:
			ret.append(varItem);
		    else:
			return varItem;

	if not varType or varType == GHS_Workspace.predefinedVarType:
	    for varItem in self.predefinedVariables:
		good = False;
		if column <= 0:
		    if value == varItem.name:
			good = True;
		    elif match and re.match(value, varItem.name):
			good = True;
		    elif not match and re.search(value, varItem.name):
			good = True;
		if not good and (column < 0 or column == 1):
		    if value == varItem.value:
			good = True;
		    elif match and re.match(value, varItem.value):
			good = True;
		    elif not match and re.search(value, varItem.value):
			good = True;
    
		if good:
		    if all:
			ret.append(varItem);
		    else:
			return varItem;

	return ret;
    # aliases for the function
    searchvariable = SearchVariable;
    SearchVar = SearchVariable;
    searchvar = SearchVariable;



class GHS_LauncherWindow(ghs_window.GHS_Window):
    """ Describe MULTI Launcher window information. """
    #
    # Initialize object
    #
    # GHS: Validated
    #
    def __init__(self, compName="", wn="", wid="0", className="",
		 regSvcName="", service=""):
	ghs_window.GHS_Window.__init__(self, compName, wn, wid, className,
				       regSvcName, service);


    #
    # Load workspace file
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def LoadWorkspaceFile(self, fileName, block=True, printOutput=True, expandFileName=True):
	if not fileName:
	    print("No workspace file name is specified.");
	    return False;
	if expandFileName:
	    fileName = GHS_ExpandFileName(fileName);
	cmd = 'LoadWorkspaceFromFile '+GHS_QuotifyString(fileName);
	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    loadworkspacefile = LoadWorkspaceFile;
    LoadWorkspace = LoadWorkspaceFile;
    loadworkspace = LoadWorkspaceFile;
    LoadWsFile = LoadWorkspaceFile;
    loadwsfile = LoadWorkspaceFile;
    LoadWs = LoadWorkspaceFile;
    loadws = LoadWorkspaceFile;


    #
    # Select a workspace as the current workspace.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def SelectWorkspace(self, wsName, block=True, printOutput=True):
	if not wsName:
	    print("No workspace name is given.");
	    return False;
	cmd = 'SelectWorkspace '+GHS_QuotifyString(wsName);
	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    selectworkspace = SelectWorkspace;
    SelWs = SelectWorkspace;
    selws = SelectWorkspace;


    #
    # Create a workspace.
    #
    # If both workspace name and working dir are specified, the function will
    # create an empty workspace with the given information.
    #
    # If the workspace name already exists, the workspace will be selected into
    # the current workspace, and the working dir (if it is specified) will be
    # applied to the existing workspace.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def CreateWorkspace(self, wsName="", workingDir="",
			block=True, printOutput=True):
	if wsName:
	    cmd = 'CreateWorkspace -name '+GHS_QuotifyString(wsName);
	else:
	    cmd = 'CreateWorkspace';
	if workingDir:
	    workingDir = GHS_ExpandFileName(workingDir);
	    cmd = cmd+' -wd '+GHS_QuotifyString(workingDir);
	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    createworkspace = CreateWorkspace;
    CreateWs = CreateWorkspace;
    createws = CreateWorkspace;
    AddWorkspace = CreateWorkspace;
    addworkspace = CreateWorkspace;
    AddWs = CreateWorkspace;
    addws = CreateWorkspace;


    #
    # Delete workspace.
    #
    # If workspace name is given, the specified workspace will be deleted.
    # If no workspace name is given and argument "delCurrentWs" is True,
    # the current workspace will be deleted.
    # Otherwise, a GUI will show up for user to choose which workspaces to be
    # deleted.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def DeleteWorkspace(self, wsName="", delCurrentWs=True,
			block=True, printOutput=True):
	if wsName:
	    cmd = 'DeleteWorkspace '+GHS_QuotifyString(wsName);
	elif delCurrentWs:
	    cmd = "DeleteWorkspace -current";
	else:
	    cmd = "DeleteWorkspace";
	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    deleteworkspace = DeleteWorkspace;
    DelWs = DeleteWorkspace;
    delws = DeleteWorkspace;


    #
    # Parse command outputs into running action list.
    #
    # GHS: Validated (indirectly, internal use only)
    #
    def ParseRunningActions(self):
	if not self.cmdExecOutput:
	    return None;
	lines = self.cmdExecOutput.split("\n");
	ret = [];
	actionRe = re.compile("^PID=");
	for line in lines:
	    if actionRe.match(line):
		ret.append(line);
	return ret;
    #
    # Get running actions.
    #
    # Return a list of string in the following format:
    #   PID=0xabdc: Action Name String
    #
    # GHS: Validated
    #
    def GetRunningActions(self, show=True):
	if not self.RunCommands("GetRunningActions", True, False):
	    return None;
	ret = self.ParseRunningActions();
	if show:
	    if self.cmdExecOutput:
		print("Running actions:");
		for action in ret:
		    print("    %s" % action);
	    else:
		print("There are no running actions.");
	return ret;
	# If necessary, we can grab the outputs by waiting for an Editor
	# window to showup.
    # Define some aliases for the function
    getrunningactions = GetRunningActions;
    #
    # Check if an action is in action list.
    #
    # GHS: Validated (internal use only)
    #
    def CheckActionInList(self, action, actionList=None):
	if actionList == None:
	    actionList = self.GetRunningActions(False);
	if not actionList:
	    return False;
	else:
	    for actionItt in actionList:
		if actionItt == action:
		    return True;
	return False;
    # Define some aliases for the function
    checkactioninlist = CheckActionInList;
    #
    # Wait for running actions to finish.
    #
    # If no old action list is given, the function will wait for all running
    # actions to finish or timeout.
    #
    # If an old action list is give, the function will wait for all new
    # running actions (not in the old action list) to finish or timeout.
    #
    # If duration is a negavive number, we will wait until the corresponding
    # running actions to finish.
    #
    # If duration is 0.0, we only check the running action list once.
    # If duration is a positive number, we wait for that number of seconds
    # at most.
    #
    # Return True if the corresponding running actions are finished, False
    # otherwise.
    #
    # GHS: Validated
    #
    def WaitForActionsToFinish(self, oldActionList, duration=0.0,
			       warnIfNotFinish=False):
        if duration > 0.0:
	    endTime = time.time()+duration;
        goon = True;
	while goon:
	    actions = self.GetRunningActions(False);
	    goon = False;
	    if oldActionList:
		for action in actions:
		    if not self.CheckActionInList(action, oldActionList):
			goon = True;
			break;
	    elif actions:
		goon = True;
	    # Check if we should continue
	    if duration == 0.0:
		# Only check once
		break;
	    elif duration > 0.0:
		if time.time() >= endTime:
		    # Timeout
		    break;
	    if goon:
		# We sleep after checking so that we don't miss one checking.
		time.sleep(self.checkInterval);
	# Stop checking, ready to return
	if warnIfNotFinish and goon:
	    print("Action(s) are still running.");
	return not goon;
    # Define some aliases for the function
    waitforactionstofinish = WaitForActionsToFinish;
    WaitToFinish = WaitForActionsToFinish;
    waittofinish = WaitForActionsToFinish;
    Wait = WaitForActionsToFinish;
    wait = WaitForActionsToFinish;



    #
    # Run an action in a workspace's action sequence.
    #
    # If no workspace name is given, the current workspace in MULTI Launcher
    # is applied.
    # If no action sequence name is given, all enabled actions in the
    # workspace are applied.
    # If no action index is given or the action index is less than 0,
    # all enabled actions in the corresponding action sequence are executed.
    #
    # GHS: Validated
    #
    def RunWorkspaceAction(self, workspaceName="", actionSequenceName="",
		  actionIndex=-1, waitPeriodToFinish=0.0):
	self.CleanCmdExecVariables();
	if waitPeriodToFinish > 0.0:
	    actionList = self.GetRunningActions(False);
	else:
	    actionList = None;
	cmd = "RunAction";
	if workspaceName:
	    cmd = cmd + ' -workspace ' + GHS_QuotifyString(workspaceName);
	if actionSequenceName:
	    cmd = cmd + ' -seq ' + GHS_QuotifyString(actionSequenceName);
	if actionIndex >= 0:
	    cmd = cmd + ' -index ' + str(actionIndex);
	    
	if not self.RunCommands(cmd, True, True):
	    return False;

	ret = True;
	if waitPeriodToFinish > 0.0:
	    ret = self.WaitForActionsToFinish(actionList,
					waitPeriodToFinish,
					True);
	if self.cmdExecOutput:
	    print("%s" % self.cmdExecOutput);

	# If necessary, we can grab the outputs by waiting for an Editor
	# window to showup.
	return ret;
    # Define some aliases for the function
    runworkspaceaction = RunWorkspaceAction;
    RunWsAction = RunWorkspaceAction;
    runwsaction = RunWorkspaceAction;
    #
    # Run an ad hoc action specified in the arguments.
    #
    # If "workingDir" is specified, the action will be run in the working dir.
    # If no "workingDir" is specified, the action will be run in the
    # specified workspace context or the current workspace context if
    # no workspace name is specified.
    #
    # GHS: Validated
    #
    def RunAction(self, actionType, actionArgs="",
		  workingDir="", wsName="", waitPeriodToFinish=0.0):
	self.CleanCmdExecVariables();
	if waitPeriodToFinish > 0.0:
	    actionList = self.GetRunningActions(False);
	else:
	    actionList = None;
	if not actionType:
	    print("No action type is specified.");
	    return False;
	if not isinstance(actionType, str):
	    print("Action type must be a string.");
	    return False;

	cmds = 'RunAction -type '+GHS_QuotifyString(actionType);
	if actionArgs:
	    cmds = cmds+' -arg '+GHS_QuotifyString(actionArgs);
	if workingDir:
	    workingDir = GHS_ExpandFileName(workingDir);
	    cmds = cmds+' -wd '+GHS_QuotifyString(workingDir);
	if wsName:
	    cmds = cmds+' -workspace '+GHS_QuotifyString(wsName);

	if not self.RunCommands(cmds, True, True):
	    return False;

	ret = True;
	if waitPeriodToFinish > 0.0:
	    ret = self.WaitForActionsToFinish(actionList,
					waitPeriodToFinish,
					True);

	# If necessary, we can grab the outputs by waiting for an Editor
	# window to showup.
	return ret;
    # Define some aliases for the function
    runaction = RunAction;



    #
    # Add an action.
    #
    # If no workspace name is given, the action will be added to the current
    # workspace.
    # Working dir is only used when workspace name is given and the workspace
    # name does not exist (a new workspace will be created).
    #
    # If indexInActionSequence is negative, the action will be added to the
    # end of the action list of the corresponding action sequence.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def AddAction(self, actionType, actionArgs="",
		    actionSequenceName="Startup",
		    indexInActionSequence=-1,
		    wsName="", workingDir="",
		    block=True, printOutput=True):
	if not actionType:
	    print("No action type is given.");
	    return False;
	if not actionSequenceName:
	    print("No action sequence name is given.");
	    return False;

	cmd = 'AddAction -type '+GHS_QuotifyString(actionType);
	if actionArgs:
	    cmd = cmd+' -arg '+GHS_QuotifyString(actionArgs);
	if wsName:
	    cmd = cmd+' -workspace '+GHS_QuotifyString(wsName);
	if workingDir:
	    workingDir = GHS_ExpandFileName(workingDir);
	    cmd = cmd+' -wd '+GHS_QuotifyString(workingDir);
	cmd = cmd+' -seq '+GHS_QuotifyString(actionSequenceName);
	if indexInActionSequence >= 0:
	    cmd = cmd+' -index '+str(indexInActionSequence);

	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    addaction = AddAction;


    #
    # Delete an action of the specified workspace at the specified position
    # (0 based) in the specified action sequence.
    #
    # If actionSequenceName is given but indexInActionSequence is negative,
    # all actions in the action sequence will be deleted.
    #
    # If no action sequence name is given, the whole workspace will be deleted.
    #
    # If no workspace name is given, the deletion will be applied to the
    # current workspace.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def DeleteAction(self, actionSequenceName="",
			indexInActionSequence=-1,
			wsName="", 
			block=True, printOutput=True):
#	if not actionSequenceName:
#	    print("No action sequence name is given.");
#	    return False;

	cmd = 'DeleteAction';
	if wsName:
	    cmd = cmd+' -workspace '+GHS_QuotifyString(wsName);
	if actionSequenceName:
	    cmd = cmd+' -seq '+GHS_QuotifyString(actionSequenceName);
	if indexInActionSequence >= 0:
	    cmd = cmd+' -index '+str(indexInActionSequence);

	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    deleteaction = DeleteAction;
    DelAction = DeleteAction;
    delaction = DeleteAction;


    #
    # Add a variable to the workspace (local) or the whole system (global).
    #
    # If the variable already exists, the existing variable's value will be
    # changed to the given value.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def AddVariable(self, varName, varValue, globalVar=False, wsName="",
		    block=True, printOutput=True):
	if not varName:
	    print("No variable name is given.");
	    return False;
	if not isinstance(varValue, str):
	    varValue = str(varValue);
	cmd = "mb_ManipulateVariable";
	if globalVar:
	    cmd = cmd + " -global";
	else:
	    cmd = cmd + " -local";
	cmd = cmd + " -add";
	if wsName:
	    cmd = cmd + " -workspace " + GHS_QuotifyString(wsName);
	cmd = cmd + " -name " + GHS_QuotifyString(varName) + " -value " + GHS_QuotifyString(varValue);

	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    addvariable = AddVariable;
    AddVar = AddVariable;
    addvar = AddVariable;

    #
    # Change the value of a variable in the workspace (local) or the whole
    # system (global).
    #
    # If the variable does not exist in the workspace, it will be added to the
    # workspace.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def ChangeVariable(self, varName, varValue, globalVar=False, wsName="",
		       block=True, printOutput=True):
	if not varName:
	    print("No variable name is given.");
	    return False;
	if not isinstance(varValue, str):
	    varValue = str(varValue);
	cmd = "mb_ManipulateVariable";
	if globalVar:
	    cmd = cmd + " -global";
	else:
	    cmd = cmd + " -local";
	cmd = cmd + " -change";
	if wsName:
	    cmd = cmd + " -workspace " + GHS_QuotifyString(wsName);
	cmd = cmd + " -name " + GHS_QuotifyString(varName) + " -value " + GHS_QuotifyString(varValue);

	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    changevariable = ChangeVariable;
    ChangeVar = ChangeVariable;
    changevar = ChangeVariable;

    #
    # Delete a variable from the workspace (local) or the whole system (global).
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def DeleteVariable(self, varName, globalVar=False, wsName="",
		       block=True, printOutput=True):
	if not varName:
	    print("No variable name is given.");
	    return False;
	cmd = "mb_ManipulateVariable";
	if globalVar:
	    cmd = cmd + " -global";
	else:
	    cmd = cmd + " -local";
	cmd = cmd + " -delete";
	if wsName:
	    cmd = cmd + " -workspace " + GHS_QuotifyString(wsName);
	cmd = cmd + " -name " + GHS_QuotifyString(varName);

	return self.RunCommands(cmd, block, printOutput);
    # Define some aliases for the function
    deletevariable = DeleteVariable;
    DelVar = DeleteVariable;
    delvar = DeleteVariable;

    #
    # Save workspace into file.
    #
    # If no workspace name is given, the current workspace will be saved.
    #
    # If no file name is given, user will be asked to choose a file name
    # via file chooser.
    #
    # Return True(success) or False(failure).
    #
    # GHS: Validated
    #
    def SaveWorkspaceIntoFile(self, fileName="", wsName="",
				block=True, printOutput=True,
				expandFileName=True):
	cmd = 'SaveWorkspaceIntoFile -quiet';
	if wsName:
	    cmd = cmd+' -workspace '+GHS_QuotifyString(wsName);
	if fileName:
	    if expandFileName:
		fileName = GHS_ExpandFileName(fileName);
	    cmd = cmd+' '+GHS_QuotifyString(fileName);
	return self.RunCommands(cmd, block, printOutput);	
    # Define some aliases for the function
    saveworkspaceintofile = SaveWorkspaceIntoFile;
    SaveWsIntoFile = SaveWorkspaceIntoFile;
    savewsintofile = SaveWorkspaceIntoFile;
    SaveWs = SaveWorkspaceIntoFile;
    savews = SaveWorkspaceIntoFile;


    #
    # Get workspace name list.
    #
    # Retuen a list of string for the workspace names.
    #
    # GHS: Validated
    #
    def GetWorkspaces(self):
	return self.GetPdMenu("WorkSpace");
    # Define some aliases for the function
    getworkspaces = GetWorkspaces;
    GetWses = GetWorkspaces;
    getwses = GetWorkspaces;

    #
    # Get a workspace's all information, including the global variables in the
    # current environment.
    #
    # Reurn a GHS_Workspace object on success or None on failure.
    #
    # GHS: Validated
    #
    def GetWorkspaceInformation(self, wsName="", original=True):
	if original:
	    cmd = "mb_GetWorkspaceInfo -original"
	else:
	    cmd = "mb_GetWorkspaceInfo -substituted"
	if wsName:
	    cmd = cmd + " " + GHS_QuotifyString(wsName);

	if not self.RunCommands(cmd, True, False) or not self.cmdExecOutput:
	    return None;

	# Parse the output into GHS_Workspace.
	lines = self.cmdExecOutput.split("\n");
	ret = GHS_Workspace("");
	itemLead = "    ";
	expected = "";
	for line in lines:
	    if not ret.name:
		res = re.match("^Workspace Name:(.*)$", line);
		if res:
		    ret.name = (res.group(1));
		    continue;
	    if ret and not ret.workingDir:
		res = re.match("^Working Dir:(.*)$", line);
		if res:
		    ret.workingDir = (res.group(1));
		    continue;

	    res = re.match("^(Local Variables):(.*)$", line);
	    if res:
		expected = res.group(1);
		continue;
	    res = re.match("^(Global Variables):(.*)$", line);
	    if res:
		expected = res.group(1);
		continue;
	    res = re.match("^(Pre-defined Variables):(.*)$", line);
	    if res:
		expected = res.group(1);
		continue;
	    res = re.match("^(Actions):(.*)$", line);
	    if res:
		expected = res.group(1);
		continue;

	    if not expected:
		continue;
	    elif expected == "Local Variables":
		res = re.match("^"+itemLead+"\[(.*)\]->\[(.*)\]$", line);
		if res:
		    var = GHS_Variable(res.group(1), res.group(2), GHS_Workspace.localVarType);
		    ret.AddVariable(var);
		else:
		    print("Unknown local variable '%s'" % (line));
		    return ret;
	    elif expected == "Global Variables":
		res = re.match("^"+itemLead+"\[(.*)\]->\[(.*)\]$", line);
		if res:
		    var = GHS_Variable(res.group(1), res.group(2), GHS_Workspace.globalVarType);
		    ret.AddVariable(var);
		else:
		    print("Unknown global variable '%s'" % (line));
		    return ret;
	    elif expected == "Pre-defined Variables":
		res = re.match("^"+itemLead+"\[(.*)\]->\[(.*)\]$", line);
		if res:
		    var = GHS_Variable(res.group(1), res.group(2), GHS_Workspace.predefinedVarType);
		    ret.AddVariable(var);
		else:
		    print("Unknown pre-defined variable '%s'" % (line));
		    return ret;
	    elif expected == "Actions":
		res = re.match("^"+itemLead+"(\w*?):\[(.*?)\]:\[(.*?)\]:\[(.*)\]$", line);
		if res:
		    asItem = ret.SearchActionSequence(res.group(2), True);
		    if not asItem:
			asItem = GHS_ActionSequence(res.group(2));
			ret.actionSequences.append(asItem);
		    action = GHS_Action(res.group(3), res.group(4),
					res.group(1) == "Enabled");
		    asItem.AddChild(action);
		else:
		    print("Unknown action item '%s'" % (line));
		    return ret;
	    else:
		print("Unknown output item '%s'" % (line));
		return None;

	return ret;
    # Define some aliases for the function
    getworkspaceinformation = GetWorkspaceInformation;
    GetWorkspaceInfo = GetWorkspaceInformation;
    getworkspaceinfo = GetWorkspaceInformation;
    GetWsInfo = GetWorkspaceInformation;
    getwsinfo = GetWorkspaceInformation;


    ##########################################################################
    #
    # More APIs......
    #
    ##########################################################################



# Define some aliases for the class
#ghs_launcherwindow = GHS_LauncherWindow;
