#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
測定及び解析シーケンスの作成・編集と実行
[inamura 160822] Added button to change current directory
[inamura 160229] Bugfix the freeze at ModalDialog.Destroy() on cocoa wx
[inamura 160220] Added method to write the log file
[inamura 150623] Fixed the issue about wrong treatment of argument in TEXT on rendering in RenderLine
[inamura 141224] Improved the arguments format in saved scripts, which format changed from only value to both label and value
                 ( changed methods of RenderLine and MakeLine in Rendering class )
[inamura 140818] Improved procedure to append facade functions from "Sequencer_fa*.py" 
[inamura 140323] Expanded the number of arguments to 15 and improved analysis arguments and default values from facade functions
[inamura 120522] Improve Resume process ( if selected command are executing, ignore it )
[inamura 120424] VisualPanel comes over the other windows
                 Fix actions of Enable toggle on Remove,Copy buttons
                 Enable to remove all selected commands at a time
[inamura 120404] improve button working for resumption from stop
                 Enable auto finding command to be resumed
[inamura 120403] Enable to edit sequence on executing
                 Improving buttons working on editing commands
[inamura 120321] Initial Sequence can be set on start up
[inamura 110111] Put back reserved arguments 
[inamura 110105] Add splash picture
[inamura 101228] Change GUI design and Add the COPY/PASTE
"""
import os
import sys
import time
import threading
import thread
from types import *
import codecs
#import vis.UtilPlot as UtilPlot
import datetime ##[inamura 160220]
from PySide import QtCore, QtGui
from ana.ui_SequencerQ import Ui_MainWindow, Ui_Dialog, Ui_visframe
import vis.UtilQt as UtilQt

#######################################
#    Definitions
#######################################

VISMODULE = 'VisualModuleQ'
INITSEQFILE = "InitialSequence.pmt"     ##[inamura 120321]
BASEFACADEFILE = "Sequencer_fa*.py"     ##[inamura 140818]
BASELOGFILE = "log.Sequencer2_%s_%05d"    ##[inamura 160220]
#######################################
#  Argument
#######################################  
class Argument(object):
    """
     引数データクラス
    """
    #########################################
    def __init__(self):
        """
        コンストラクタ
        @param  無し 
        @retval 無し

        """ 
        # 引数のラベル
        self.label = ""
        # 引数の型、"string", "float", "integer", "boolean", "retval" 
        self.type = ""
        # 引数の値
        self.value = "" 
        # 引数の説明、ツールチップに表示
        self.tip = "" 

    #########################################
    def Copy(self):
        """
        新しい引数インスタンスを作り内容をコピー
        @param  無し
        @retval コピー後の引数インスタンス
        """ 
        # 新しい引数インスタンスの作成
        narg = Argument()
        # 新しいインスタンスへデータをコピー
        narg.label = self.label 
        narg.type = self.type
        narg.value = self.value
        narg.tip = self.tip
        
        return narg
        
#######################################
#  ReturnValue
#######################################  
class ReturnValue(object):
    """
     戻り値データクラス
    """
    #########################################
    def __init__(self):
        """
        コンストラクタ
        @param  無し 
        @retval 無し
        """ 
        # 戻り値のラベル
        self.label = None
        # 戻り値の説明、ツールチップに表示
        self.tip = "" 
        # 戻り値(関数実行後に、値が入る)
        self.retResult = None        

    #########################################
    def Copy(self):
        """
        新しい戻り値インスタンスを作り内容をコピー
        @param  無し
        @retval コピー後の戻り値インスタンス
        """
        # 新しい戻り値インスタンスの作成
        nret = ReturnValue()
        # 新しいインスタンスへデータをコピー
        nret.label = self.label 
        nret.tip = self.tip
        nret.retResult = self.retResult
        return nret 
        
#######################################
#  Function
#######################################  
class Function(object):
    """
     関数データクラス
    """
    #########################################
    def __init__(self):
        """
        コンストラクタ
        @param  無し 
        @retval 無し
        """ 
        # 関数名称(モジュール名付き)
        self.mfname = ""
        # 関数の実行アドレス
        self.fobj= None
        # 関数ドキュメント
        self.fdoc = "" 
        # 引数データインスタンスのリスト
        self.args = []
        # 戻り値データのインスタンス
        self.retn = None 
        # ステップ状態  -1:未実行(実行不可) 0: 未実行(実行可)、1: 実行中、2:正常終了、3: 異常終了
        self.stat = 0
        # 開始時間(文字列)
        self.beginTime = ""
        # 終了時間(文字列) 
        self.endTime = ""
    
    #########################################
    def Copy(self):
        """
        新しい関数インスタンスを作り内容をコピー
        @param  無し
        @retval コピー後の関数インスタンス
        """ 
        # 新しい関数インスタンスの作成
        nfunc = Function()
        nfunc.mfname = self.mfname
        nfunc.fobj = self.fobj
        # 引数をコピー
        for arg in self.args:
            narg = arg.Copy()
            nfunc.args.append(narg)    
        # 戻り値をコピー 
        if self.retn != None:   
            nfunc.retn = self.retn.Copy()
            
        return nfunc    

    #########################################
    def ClearResult(self):
        """
        関数の実行結果をクリア
        @param  無し
        @retval 無し
        """             
        self.stat = 0
        if self.retn != None:
            del self.retn.retResult ##[inamura 120128]
            self.retn.retResult = None        
        self.beginTime = ""
        self.endTime = ""
       
#######################################
#  ExecSequence
#######################################  
class ExecSequence(object):
    """
     サブスレッド上で、シーケンスを実行する
    """

    #########################################
    def __init__(self, lock):
        """
        コンストラクタ
        @param  lock  シーケンス排他制御用のロック 
        @retval 無し
        """ 
        self.lock = lock
        # 初期化
        self.rd = Rendering(None)
        self.stopflag = False
        # 実行状態　-1:停止状態  0:実行開始開始前  1:実行中
        self.status = -1
        # 実行中ステップ番号
        self.execNo = 0        
        # エラー状態、0:エラー無し  1:実行前エラー  2: 実行中エラー
        self.erstatus = 0
        # エラーメッセージ
        self.errmsg = ""
        self.LogFile=None ##[inamura 160220]
    #############################################
    def GetTimeNow(self):
        """
        現在の時刻を、文字列形式で返す
        @param  無し
        @retval 時刻文字列　
        """ 
        # 時間を取得
        tplTime = time.localtime()
        # 時:分:秒　の文字列を作成
        strTime = "%2d:%02d:%02d" % (tplTime[3], tplTime[4], tplTime[5])
        
        return strTime

    #############################################
    def MakeHistory(self):
        """
        現在の行以前のスクリプトを返す
        @param  無し
        @retval 実行履歴(マルチ文字列)　
        """
        history = "" 
        # 最初の行か
        if self.execNum > 0:
            # 現在の行の前まで
            for i in range(self.execNum):
                func = self.funcs[i]
                line = self.rd.MakeLine(func)
                history = history + line + "\n"
           
        return history                  


    #############################################
    def OnStart(self, index, funcs):
        """
        一連の関数の実行開始
        @param  ndex  開始インデックス
        @param  funcs  関数リスト
        @retval 無し
        """ 
        self.status = 0
        self.erstatus = 0
        self.funcs = funcs
        # 指定行からスタート
        self.execNum = index 
        self.stopflag = False
     
        # サブスレッドスタート
        th = threading.Thread(target=self.__ExecFunc, args=(self.funcs,))
        th.setDaemon(True)
        th.start()

    #############################################
    def OnStop(self):
        """
        一連の関数の実行停止
        @param  無し
        @retval 無し
        """ 
        self.stopflag = True # ユーザ停止

    #############################################        
    def __ExecFunc(self, funcs) :
        """
        サブスレッドにて、要求された関数群を実行する
        @param  funcs 関数リスト
        @retval 無し
        """ 
        self.status = 1
        numFuncs = len(funcs)
        # 関数リスト中の関数を1個づつ実行

        while self.execNum < numFuncs:
            # シーケンスリストから関数を取得
            self.lock.acquire()
            func = funcs[self.execNum]

            ##[inamura 160220]-->
            if self.LogFile!=None:
                try:
                    ff = open( self.LogFile, "a" )
                    dt = datetime.datetime.now()
                    msg = "[%s] %s\n"%(dt.strftime("%Y%m%d%H%M%S"),func.mfname)
                    msg += "      Args: "
                    for arg in func.args:
                        msg += "%s=%s "%(arg.label,str(arg.value) )
                    msg += "\n"
                    ff.write( msg )
                    ff.close()
                except:
                    self.LogFile = None
            ##<--[inamura 160220]

            # 引数リストを準備
            execargs = []
            #ret = True
            # 引数リストを解析
            for arg in func.args:
                # 引数が特別予約語: 履歴要求か
                if arg.label == "HISTORY":
                    execarg = self.MakeHistory()
                else:
                    # 引数を解釈して実行形式に変換    
                    execarg = self.rd.ChangeArg(arg, self.funcs)
                # 正しく変換されていなければ
                if execarg == None:
                    # エラー中止
                    self.lock.release()
                    self.erstatus = 1
                    self.ermessage = "\nArgument %s of %s error!!" % (arg.label, func.mfname)
                    break
                execargs.append(execarg)
                
            # 中断または中止要求があれば、
            if self.erstatus > 0 or self.stopflag:
                break
            # 開始時間を設定
            func.beginTime = self.GetTimeNow()
            # 関数を実行
            func.stat = 1    # 実行中
            fobj = func.fobj
            self.lock.release()
            try:
                # 関数の実行
                time.sleep(0.6)
                ret = apply(fobj, execargs)
            # ユーザワーニングか    
            except UserWarning, ex:
                # エラー中止
                self.ermessage = "%s: \n%s" % (func.mfname, ex)
                self.erstatus = 2  # 実行中エラー
                break
            # ユーザワーニング以外の例外発生
            except:
                # エラー中止
                self.ermessage = func.mfname
                self.erstatus = 2  # 実行中エラー
                func.stat = 3 
                # 端末に標準エラーを表示するために、例外を再発生
                raise
                break
            else:
                self.lock.acquire()

                # 実行中にステップ状態が変更されてないかったなら
                if func.stat == 1:
                    # 関数の戻り値が指定されているなら
                    if func.retn != None: 
                        if ret != None:
                            # 実行結果を関数リストに入れる
                            func.retn.retResult = ret
                    # 終了時間を設定
                    func.endTime = self.GetTimeNow()
                    func.stat = 2    # 正常終了

                self.lock.release()
                # 関数実行中に中止要求があったか
                if self.stopflag:
                    break
                # 実行中ステップのインデックスをインクリメント         
                self.execNum += 1
        # 異常終了か
        if self.erstatus :
            self.lock.acquire()
            func.stat = 3    # 異常終了

            self.lock.release()
        # シーケンスの終了

        self.status = -1
    ##[inamura 160220]-->
    #########################################
    def SetLogFileName(self, fname):
        """
        """
        self.LogFile=fname
    ##<--[inamura 160220]

#######################################
# FunctionTree
#######################################  
class FunctionTree(object):
    """
     関数ツリークラス

    """
    #########################################
    def __init__(self, frame):
        """
        コンストラクタ
        @param  frame   親ウィンドウ(mainframe)のID
        @retval 無し
        """ 
        self.frame = frame
        
    #########################################
    def MakeNode(self, tree, rootName, modules):
        """
        関数ツリーのノード作成
        @param  tree      ツリーのIDインスタンス
        @param  rootName  ツリーの root 名称文字列
        @param  modules   ファサードモジュールリスト
        @retval 関数登録リスト
        """ 
        self.tree = tree
        # ファサードモジュールクラスのインスタンスを取得
        self.fm = FacadeModule()
        # 関数登録リストの準備
        self.rgfuncs = []
        # ルートノードを作成
        #root = self.tree.AddRoot(rootName)
        root = QtGui.QTreeWidgetItem( self.tree )
        root.setText(0,rootName)
        # ルートの直下のノードを作成
        for module in modules:

            # 文字列 = モジュール名か
            if type(module) == type(""):
                # サブノードを作成
                self.MakeSubNode(root, module)
            # リストまたはタプルであればモジュール群
            elif type(module) == type(()) or type(module) == type([]):
                    
                # モジュール名に文字列を入力し空白のみでなければ
                if type(module[0]) == type("") and len(module[0].strip()) > 0:
                    # モジュール群のカテゴリー名をサブノードに作る
                    #subID = self.tree.AppendItem(root, module[0])
                    subID = QtGui.QTreeWidgetItem( root )
                    subID.setText(0, module[0])
                    # サブノードの下に各モジュールのノードを作成
                    for modl in module[1]:
                        # サブノードを作成
                        self.MakeSubNode(subID, modl)
                    #self.tree.Expand(subID)
                    self.tree.expandItem(subID)

        # Functions のサブノードを展開
        #self.tree.Expand(root)
        self.tree.expandItem(root)
        
        return self.rgfuncs
    
    #########################################
    def MakeSubNode(self, parentNode, module):
        """
        関数一覧ツリーのサブノード作成
        @param  parentNode  親ノードのID 
        @param  module      インポート対象のモジュール 
        @retval 無し
        """ 
        # 文字列でなければ
        if type(module) != type(""):
            return

        # 関数登録モジュールのインポートとスクリプトファイルの読み込み
        try:
            funcs = self.fm.GetFuncs(module)
        except UtilQt.PlotException, ex:
            UtilQt.PlotMessage(self.frame, ex)
            return
        
        # モジュール名があれば
        if not funcs is None:
            # サブノード作成
            #subID = self.tree.AppendItem(parentNode, module)
            subID = QtGui.QTreeWidgetItem(parentNode)
            subID.setText(0, module)

            # サブノードの下へ関数名を登録
            for func in funcs:
                #self.tree.AppendItem(subID, func.mfname)
                tmp = QtGui.QTreeWidgetItem(subID)
                tmp.setText(0,func.mfname)
            # リストに追加
            self.rgfuncs.extend(funcs)
                    

#######################################
# Rendering 
#######################################  
class Rendering(object):
    """
     シーケンス解析クラス

    """
    #########################################
    def __init__(self, frame):
        """
        コンストラクタ
        @param  frame   親ウィンドウ(mainframe)のID
        @retval 無し
        """ 
        self.frame = frame
        
    ##########################################
    def RenderLine(self, rgfuncs, line) :
        """
        関数行を解釈
        @param  funcs 関数ディクショナリ
        @param  line 1行の文字列
        @retval 関数データ
        """ 
        cnt = line.find('=')
        cnt0 = line.find('(')
        # 戻り値が指定されているか
        if cnt > 0 and cnt < cnt0:
            retStr = line[:cnt]
            func = line[cnt+1:]
            retStr = retStr.strip()
        else:
            retStr = None
            func = line
        fflag = True
        n = func.find('(') 
        funcName = func[:n].strip()

        # 関数一覧から検索
        for func in rgfuncs: 
            # 関数名称か

            if func.mfname == funcName:
                fflag = False
                break

        try:
            # 登録関数名になければ
            if fflag:
                # 不正な関数名
                raise UtilQt.PlotException('Sequencer', 'S005', (funcName,))
        except UtilQt.PlotException, ex:
            UtilQt.PlotMessage(self.frame, ex)
            return None
        
        ofunc = func.Copy()
        
        # 引数を取り出す
        n0 = line.find('(')
        n1 = line.rfind(')')
        args = line[n0+1:n1]
        ##[inamura 141224]-->
        ##
        ## store string argument and replace it with keyword
        re_args = ""
        ind =0
        st_param_ind = 0
        st_param_dic = {}
        key_arg_base = "SEQUENCERPARAM"
        while(ind<len(args)):
            a_char = args[ind]
            if (a_char=='"'):
                key_arg = "%s%02d"%(key_arg_base,st_param_ind)
                ind2 = args[(ind+1):].find('"')
                st_param_dic[ key_arg ] = args[ind+1:(ind+1+ind2)]
                re_args += key_arg
                ind = (ind+1)+ind2+1
                if ind<(len(args)-1):
                    re_args += args[ind]
                st_param_ind +=1
            else:
                re_args +=a_char
            ind +=1
        
        ## separate each argument and check the number of arguments
        param_set_list = re_args.split(",")
        try:
            if (len(param_set_list)>len(ofunc.args)):
                raise UtilQt.PlotException('Sequencer', 'S006', (funcName,))
        except UtilQt.PlotException, ex:
            UtilQt.PlotMessage(self.frame, ex)
        
        ## analysis of each argument
        isUsedArgDict = {}
        for arg in ofunc.args:
            isUsedArgDict[ arg.label ] = False
        
        ind_in_args = 0
        for a_param_set in param_set_list:
            ind2 = a_param_set.find("=")
            if ind2!=-1:
                ## an argument is <label>=<val> format
                arg_label = a_param_set[:ind2]
                arg_val =   a_param_set[(ind2+1):]
                arg_lavel = arg_label.strip() ## [inamura 150623]
                arg_val = arg_val.strip()     ## [inamura 150623]
                for arg in ofunc.args:
                    if arg.label==arg_label:
                        if (arg_val.find(key_arg_base)==0):
                            arg_val = st_param_dic[ arg_val ]
                        self.CheckArgType( arg, arg_val )
                        isUsedArgDict[ arg.label ] = True
                        break
                    else:
                        pass
            else:
                ## an argument has only <val> 
                while(True):
                    ## seek empty argument
                    if isUsedArgDict[ ofunc.args[ ind_in_args ].label ]:
                        ind_in_args+=1
                        if ind_in_args>=len( ofunc.args ):
                            raise UtilQt.PlotException('Sequencer', 'S006', (funcName,))
                    else:
                        break
                arg_val = a_param_set.strip()  ## [inamura 150623]
                if (arg_val.find(key_arg_base)==0):
                    arg_val = st_param_dic[ arg_val ]
                self.CheckArgType( ofunc.args[ ind_in_args ], arg_val )
                ind_in_args+=1

        """        
        # 引数リストを準備
        lst = []
        # 文字列コード
        scode = None
        n0 = 0
        for i in range(len(args)):
            # 文字列の中でなければ
            if scode == None:
                # カンマであれば
                if args[i] == ',':
                    arg = args[n0:i].strip()
                    # 引数をリストに登録
                    lst.append(arg)
                    n0 = i+1
                # 文字列の開始か    
                elif args[i] == '"' or args[i] == "'":
                    scode = args[i]
            # 文字列の終了か        
            elif scode == args[i]:
                scode = None
        # 最後の引数        
        arg = args[n0:].strip()
        lst.append(arg)        

        try:
            # 引数の数のチェック
            if len(lst) != len(func.args):
                raise UtilPlot.PlotException('Sequencer', 'S006', (funcName,))
        except UtilPlot.PlotException, ex:
            UtilPlot.PlotMessage(self.frame, ex)
        
        i = 0
        for arg in ofunc.args:
            # 引数の型をチェックし、OKであれば読み込み
            self.CheckArgType(arg, lst[i])  
            i += 1
        """
        ##<--[inamura 141224]
        # 戻り値が指定されているなら
        if ofunc.retn != None:
            ofunc.retn.label = retStr
        return ofunc
                  

    #########################################
    def MakeLine(self, func, isSaveToFile=False):
        """
        リストに表示する文字列を作る
        @func    　　関数データ
        @retval      表示ストリング
        """ 
        # 戻り値が指定されているか
        if func.retn == None:
            strLine = ""
        else:
            strLine = func.retn.label + " = "
     
        strLine = strLine + func.mfname + '('
        # 引数の文字列を作る
        strArg = ""
        for arg in func.args:
            # 引数の値を取得

            item = arg.value
                
            # 引数の属性は文字列か        
            if arg.type == "string":
                if item == "":
                    item = '""'
                elif item == '':
                    item = "''"
                else:
                    # 最初の文字が、文字列記号でなければ
                    if item[0] != '"' and item[0] != "'":
                        if item.find('"') > 0:
                            item = "'" + item + "'"
                        else:
                            item = '"' + item + '"'
                        
            # 最初の引数か
            if len(strArg) == 0:
                if (isSaveToFile):
                    strArg = strArg + "%s=%s"%(arg.label,item)  ##[inamura 141224]
                else:
                    strArg = strArg + item
            else:
                if (isSaveToFile):
                    strArg = strArg + ",%s=%s"%(arg.label,item)  ##[inamura 141224]
                else:
                    strArg = strArg + ", " + item
        # 引数を加えて関数の括弧を閉じる
        strLine = strLine + strArg + ')'
        return strLine

    #########################################
    def CheckArgType(self, arg, item):
        """
        引数の型チェック
        @param  arg　　引数リスト
        @param item    引数(文字列)
        @retval True: OK, False: NG
        """ 
        # 入力の型チェック、ただし文字列型は型チェック無しで入れ替え
        try:
            if item == "":
                raise UtilQt.PlotException('Common', 'C013', (arg.label,))
            if arg.type == "float" :
                try:
                    item = "%s" %float(item)

                except:
                    raise UtilQt.PlotException('Common', 'C027', (arg.label,))

            elif arg.type == "integer":
                try:
                    intNum = int(item)
                except:
                    raise UtilQt.PlotException('Common', 'C026', (arg.label,))
            elif arg.type == "boolean":
                if item == "True" or item == "False":
                    pass
                else:
                    raise UtilQt.PlotException('Common', 'C028', (arg.label,))
        except UtilQt.PlotException, ex:
            UtilQt.PlotMessage(self.frame, ex)
            return False
        # 型チッェク OK であれば値を入れ替え
        arg.value = item
        return True

    #############################################        
    def ChangeArg(self, val, funcs) :
        """
        引数の解析
        @param  val  引数データ
        @param  funcs 　関数の結果リスト
        @retval 変換後の引数、None の場合はエラー
        """                 
        ret = None
        try:
            if val.type == "float":
                ret = float(val.value)
            elif val.type == "integer":
                ret = int(val.value)    
            elif val.type == "string":
                ret = str(val.value.strip('"'))
            elif val.type == "retval":
                ret = None
                # 関数リストから戻り値を検索、同じラベルが複数ある場合、最後の結果が有効
                for func in funcs:
                    # 実行結果があれば
                    if func.retn != None and func.retn.retResult != None:
                        # ラベルは等しいか
                        if func.retn.label == val.value:
                            ret = func.retn.retResult
            elif val.type == "boolean":
                if val.value == "True":
                    ret = True
                elif val.value == "False":
                    ret = False
                else:
                    ret = None
        except:
            # 例外発生時、None を返す
            pass
        return ret

    #############################################        
    def CheckBackwash(self, index, funcs) :
        """
        変更があったステップの影響が及ぶステップの結果をクリア
        @param  index   当該ステップの戻り値を使用しているステップの結果をクリア
        @param  funcs 　関数の結果リスト
        @retval 変換後の引数、None の場合はエラー
        """ 

        func = funcs[index]
        # 当該ステップに戻り値がなければ
        if func.retn == None or func.retn.retResult == None:
            return
        retLabel = func.retn.label
        # 次のステップからチェック
        index += 1
        while index < len(funcs):
            for arg in funcs[index].args:
                # 引数として、変更のあったステップの結果を使用しているか
                if arg.value == retLabel:
                    # 結果をクリアするステップの影響を再帰的にチェック
                    self.CheckBackwash(index, funcs)
                    # 実行中でなければ
                    if funcs[index].stat != 1:
                        # 結果をクリア
                        funcs[index].ClearResult()
                    break
            index += 1                    

#######################################
# SequenceFile
#######################################  
class SequenceFile(object):
    """
     シーケンスファイルクラス
    """
    #########################################
    def __init__(self, frame):
        """
        コンストラクタ
        @param  frame   親ウィンドウ(mainframe)のID
        @retval 無し
        """ 
        self.frame = frame
        self.fDoc = ""
        # 解析クラスのインスタンスを取得
        self.rd = Rendering(frame)    

        # to keep path to be used
        #self.defaultpath = "" ##[inamura 110125]
        self.defaultpath = os.getcwd() ##[inamura 160822]
        
    ##########################################
    def OpenSequence(self, rgFuncs, flag, isNeedDlg=True, initFile="", defPath="") :
        """
        シーケンスファイルを開き、シーケンスを読み込む
        [inamura 120321][inamura 161216]
        @param  rgFuncs  登録されている関数のディクショナリ
        @param  flag
        @param  isNeedDlg   True: Open dialog comes up
        @param  initFile    Initial file name to be used if isNeedDlg is False
        @retval (ファイル名, 関数リスト)
        """
        ##[inamura 161216]-->
        if defPath!="":
            self.defaultpath=defPath
        ##<--[inamura 161216]
        ##[inamura 120321]-->
        if isNeedDlg:
            # PMTファイルのパスを取得
            ##[inamura 110125]-->
            if self.defaultpath=="":
                pdir = UtilQt.AcqPath().GetPmtPath(flag)
            else:
                pdir = self.defaultpath
            ##<--[inamura 110125]
            # ファイルオープンダイアログ
            filename, filt = QtGui.QFileDialog().getOpenFileName( self.frame, u"Open Sequence File ...",pdir, filter="Sequence (*.pmt)" )
            #dlg = wx.FileDialog(self.frame, 'Open Sequence File ...', pdir, style=wx.OPEN, wildcard='Sequence(*.pmt)|*.pmt') ##[inamura 110131]

            # キャンセルか
            if filename=="":
            #if dlg.ShowModal() != wx.ID_OK:
                return 


            #self.newfile = dlg.GetPath()
            #fname = dlg.GetFilename()
            self.newfile = filename
            self.defaultpath = os.path.split(self.newfile)[0] ##[inamura 110125]
            fname = os.path.split(self.newfile)[1]

            # 拡張子「.pmt」がないとき「.pmt」をつける
            if fname.find('.') < 0:
                fname = fname + ".pmt"
            if self.newfile.find('.') < 0:
                self.newfile = self.newfile + ".pmt"
        else:
            if initFile=="":
                return
            self.newfile = initFile
            fname = os.path.split(initFile)
            fname = fname[1]
        ##<--[inamura 120321]
        
        # 指定されたファイルを開く
        try:
            fp = codecs.open(self.newfile, 'r', "utf-8")
        except:
            raise UtilQt.PlotException('Common', 'C006', (fname,))
            return

        funcs = []
        aFlag = True
        # 1行づつ読み込む
        while 1:
            line = fp.readline()
            # ファイルの終わりか
            if not line:
                break
            
            # トリプルクォーテーションか
            if '"""' in line:
                if aFlag:
                    # コメントの開始
                    aFlag = False
                else:
                    # コメントの終了
                    aFlag = True

            # 有効な行か(トリプルクォーテーションで囲まれた範囲外)
            elif aFlag:
                line = line.strip()
                # コメント行か
                if len(line) > 1 and line[0] == '#':
                    pass
                # 関数か
                elif '(' in line and ')' in line:
                    # 関数を解釈
                    func = self.rd.RenderLine(rgFuncs,line)
                    # 実行可能か
                    if func != None:
                        # リストに1行を追加
                        funcs.append(func)

        # ファイルをクローズ
        fp.close()

        # 有効な行があるか
        if len(funcs) > 0:
            return (fname, funcs)
        else:
            # 無効なシーケンスファイル
            raise UtilQt.PlotException('Sequencer', 'S011', (fname,))
            return
  


    ##########################################
    def SaveSequence(self, lineFuncs, flag) :
        """
        シーケンスファイルを保存
        @param  lineFuncs  関数リスト
        @retval 保存ファイル名　
        """ 
        
        # コメント入力
        self.commret = None
        cdg = CommentDialog(self.frame, self.fDoc, self.PutComment)
        cdg.exec_() ## launch CommonDialog with a modal 
        # キャンセルされたか
        if self.commret == None:
            print "-- commret = None"
            return
        # PMTファイルのパスを取得
        ##[inamura 110125]-->
        if self.defaultpath=="":
            pdir = UtilQt.AcqPath().GetPmtPath(flag)
        else:
            pdir = self.defaultpath
        ##<--[inamura 110125]
        # ファイル保存ダイアログ
        filename,filt = QtGui.QFileDialog().getSaveFileName( self.frame, u"Save Sequence File...", pdir, filter="Sequence (*.pmt)" )
        #dlg = wx.FileDialog(self.frame, 'Save Sequence File...', pdir, \
        #                    style=wx.SAVE, wildcard='Sequence(*.pmt)|*.pmt') ##[inamura 110131]
        #if dlg.ShowModal() == wx.ID_OK:
        if filename!="":
            #self.newfile = dlg.GetPath()
            #fname = dlg.GetFilename()
            self.newfile = filename
            self.defaultpath = os.path.split(self.newfile)[0] ##[inamura 110125]
            fname = os.path.split(self.newfile)[1]
            # 拡張子が指定されていないなら
            if fname.find('.') < 0:
                # 拡張子を付加
                fname = fname + ".pmt" 
                self.newfile = self.newfile + ".pmt"
                
            # 誤った拡張子
            elif fname.find(".pmt") < 0:
                n0 = fname.find('.') 
                n1 = self.newfile.find(fname)
                fname = fname[:n0] + ".pmt"
                self.newfile = self.newfile[:n1]+ fname
            
            # 指定ファイルが既に存在するとき上書き確認ダイアログを表示
            if os.path.isfile(self.newfile):
                #dialog = wx.MessageDialog(self.frame,"%s already exists. Do you want to overwrite?" %(fname),\
                #                              'File Save',wx.YES_NO|wx.ICON_QUESTION)
                msg = u"%s already exists. Do you want to overwrite?" %(fname)
                ret = QtGui.QMessageBox().information(None,u"Warning", msg, QtGui.QMessageBox.Ok,QtGui.QMessageBox.Cancel )

                # キャンセル時
                #if dialog.ShowModal() != wx.ID_YES:
                if ret == QtGui.QMessageBox.Cancel:
                    return
                
            # 指定されたファイルを開く
            try:
                fp = codecs.open(self.newfile, 'w', "utf-8")
            except:
                raise UtilQt.PlotException('Common', 'C006', (fname,))

            # ヘッダー書き込み
            fp.write("#!/usr/bin/python\n")
            fp.write("# -*- coding: utf-8 -*-\n")
            
            # コメント書き込み
            fp.write('"""\n')
            lines = self.commret.split("\n")
            for line in lines:
                fp.write(line+"\n")
            fp.write('"""\n')
            
            # シーケンスのステップ数取得
            nline = len(lineFuncs)
            
            # インポートモジュールのリストを作る
            modules = []
            for i in range(nline):
                # 関数を取り出す

                func = lineFuncs[i]
                # モジュール名を取り出す
                module, body = func.mfname.split('.')
                # 登録済みでなければ
                if not module in modules:
                    # リストに登録
                    modules.append(module)
                    # インポート文を書き込み
                    fp.write("import " + module + "\n")

            fp.write("\n")
            # ダミー履歴を作る
            fp.write('HISTORY = ""\n')
            
            # リストの内容をファイルに書き込む
            for i in range(nline):
                line = self.rd.MakeLine(lineFuncs[i],True) ##[inamura 141224]
                fp.write(line+'\n')
   
            # ファイルをクローズ
            fp.close()
            return fname
            
    ##########################################
    def GetFileTime(self) :
        """
        直近に開いた、または保存したファイルの
        更新日を取得する
        @param   無し
        @retval 更新日時の文字列
        """ 
        try:
            ftime = os.path.getmtime(self.newfile)
        except:
            return ""
        # 最終更新時間を取得

        tplTime = time.localtime(ftime)
        # 時:分:秒　の文字列を作成
        strTime = "%4d/%02d/%02d  %02d:%02d" % (tplTime[0], tplTime[1], tplTime[2], tplTime[3], tplTime[4])

        return strTime

    ##########################################
    def GetFileDoc(self) :
        """
        直近に開いた、または保存したファイルの
        ファイルキュメントを取得する。
        ファイルの最初に出現する、トリプルクォーテーション
        で囲まれた範囲をファイルドキュメントとする。
        @param   無し
        @retval ドキュメント文字列
        """ 
        # 指定されたファイルを開く
        try:
            fp = codecs.open(self.newfile, 'r', "utf-8")
        except:
            raise UtilQt.PlotException('Common', 'C006', (fname,))
            return
        
        self.fDoc = ""
        cFlag = False
        # 1行づつ読み込む
        while 1:
            line = fp.readline()
            # ファイルの終わりか
            if not line:
                break
            # トリプルクォーテーションがあるか
            if line and line.find('"""') >= 0:
                # コメントの終了

                if cFlag:
                    break
                # コメントの開始
                else:
                    cFlag = True
                    # 先頭の空白文字と行末の改行コードを削除
                    line = line.strip()
                    line = line.rstrip()
                    # トリプルクォーテーションの後に文字列があるか
                    if len(line) > 3:
                        self.fDoc = self.fDoc + line[3:]+"\n"
 
            # コメント内か
            elif cFlag:
                self.fDoc = self.fDoc + "   " + line
        # ファイルをクローズ
        fp.close()
        return self.fDoc
    
    ##########################################
    def PutComment(self, comment) :
        """
        コメントダイアログOK 時のコールバック関数
        @param   comment コメント
        @retval 無し
        """ 
        self.commret = comment

#######################################
#  ExecVisualize
#######################################     
class ExecVisualize(QtGui.QMainWindow):
    """
    可視化処理の実行

    """
    
    #########################################
    # def __init__(self, parent, execFuncs, lock):
    def __init__(self, parent):  # 2010.01.05 Minakawa 可視化不具合対策
        """
        コンストラクタ
        @param  parent      親クラス
        @retval 無し
        """ 
        self.retFuncs = []
        # 2010.01.05 Minakawa 可視化不具合対策 -->
        #self.execFuncs = execFuncs 
        #self.lock = lock
        self.parent = parent
        self.lock = parent.lock
        # <-- 2010.01.05 Minakawa 可視化不具合対策 End
        
        # リソースファイルを取得
        #self.res = UtilPlot.ResourceFile("Sequencer")
        #self.res = UtilPlot.ResourceFile("Sequencer2") ##[inamura 140323]
        super(ExecVisualize, self).__init__(parent)
        # ウィンドウを取得
        #self.fm = self.res.GetFrame(parent.frame, 'visframe')
        #self.fm.SetIcon(UtilPlot.Images().GetMainIcon())
        self.fm = Ui_visframe()
        if self.fm == None:
            return
        self.fm.setupUi( self )
        self.rd = Rendering(self.fm)

        # Visualizer ツリーの作成と表示 
        self.VisTree()

        # 引数入力準備
        self.PrepareArg()
        # ツリー選択イベントの登録
        #self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectTree, self.tree)
        self.tree.itemSelectionChanged.connect( self.OnSelectTree )
        
        # ボタンのイベントハンドラ登録
        #self.fm.Bind(wx.EVT_BUTTON, self.OnExec, id=self.res.GetId('btExec'))
        #self.fm.Bind(wx.EVT_BUTTON, self.OnClose, id=self.res.GetId('btClose'))
        self.btExec = self.findChild(QtGui.QPushButton,u'btExec')
        self.btClose = self.findChild(QtGui.QPushButton,u'btClose')
        self.btExec.clicked.connect( self.OnExec )
        self.btClose.clicked.connect( self.OnClose )
        #クローズイベント登録
        #self.fm.Bind(wx.EVT_CLOSE, self.OnClose)
         
        # ウィンドウを表示
        #self.fm.Show()
        self.show()

    #########################################
    def VisTree(self):
        """
        Visualizer ツリーの作成と表示
        @param  無し
        @retval 無し
        """ 
        # リソースからツリーコントロールを取得     
        #self.tree = self.res.GetCtrl(self.fm, 'tree')
        self.tree = self.findChild(QtGui.QTreeWidget,u'tree')
        # ファサードモジュールクラスのインスタンスを取得
        fcmd = FacadeModule()
        # 関数登録リストの準備
        self.rgfuncs = []
        # ルートノードを作成
        #root = self.tree.AddRoot('Visualizer')
        root = QtGui.QTreeWidgetItem()
        root.setText(0,"Visualizer")
        self.tree.addTopLevelItem(root)
        # 関数登録モジュールのインポートとスクリプトファイルの読み込み
        try:
            funcs = fcmd.GetFuncs(VISMODULE)
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.fm, ex)
            UtilQt.PlotMessage(self, ex)
            return
        # サブノードの下へ関数名を登録
        for func in funcs:
            num = len(VISMODULE)+1
            funcName = func.mfname[num:]
            #self.tree.AppendItem(root, funcName)
            a_func = QtGui.QTreeWidgetItem(root)
            a_func.setText(0,funcName)
            # リストに追加
            self.rgfuncs.append(func)
        
        # Functions のサブノードを展開
        #self.tree.Expand(root)
        self.tree.expandItem(root)
        
    #########################################
    def PrepareArg(self):
        """
        引数設定関連のコントロール取得
        @param  無し 
        @retval 無し
        """ 
        # 引数文字列とテキストボックスのコントロールを取得
        """
        argpanel = self.res.GetCtrl(self.fm, 'argpanel')
        argst1 = self.res.GetCtrl(argpanel, 'argst1')
        argtx1 = self.res.GetCtrl(argpanel, 'arg1')
        argst2 = self.res.GetCtrl(argpanel, 'argst2')
        argtx2 = self.res.GetCtrl(argpanel, 'arg2')
        argst3 = self.res.GetCtrl(argpanel, 'argst3')
        argtx3 = self.res.GetCtrl(argpanel, 'arg3')
        argst4 = self.res.GetCtrl(argpanel, 'argst4')
        argtx4 = self.res.GetCtrl(argpanel, 'arg4')
        argst5 = self.res.GetCtrl(argpanel, 'argst5')
        argtx5 = self.res.GetCtrl(argpanel, 'arg5')
        argst6 = self.res.GetCtrl(argpanel, 'argst6')
        argtx6 = self.res.GetCtrl(argpanel, 'arg6')
        argst7 = self.res.GetCtrl(argpanel, 'argst7')
        argtx7 = self.res.GetCtrl(argpanel, 'arg7')
        argst8 = self.res.GetCtrl(argpanel, 'argst8')
        argtx8 = self.res.GetCtrl(argpanel, 'arg8')
        ##[inamura 140323]--
        argst9 = self.res.GetCtrl(argpanel, 'argst9')
        argtx9 = self.res.GetCtrl(argpanel, 'arg9')
        argst10 = self.res.GetCtrl(argpanel, 'argst10')
        argtx10 = self.res.GetCtrl(argpanel, 'arg10')
        argst11 = self.res.GetCtrl(argpanel, 'argst11')
        argtx11 = self.res.GetCtrl(argpanel, 'arg11')
        argst12 = self.res.GetCtrl(argpanel, 'argst12')
        argtx12 = self.res.GetCtrl(argpanel, 'arg12')
        argst13 = self.res.GetCtrl(argpanel, 'argst13')
        argtx13 = self.res.GetCtrl(argpanel, 'arg13')
        argst14 = self.res.GetCtrl(argpanel, 'argst14')
        argtx14 = self.res.GetCtrl(argpanel, 'arg14')
        argst15 = self.res.GetCtrl(argpanel, 'argst15')
        argtx15 = self.res.GetCtrl(argpanel, 'arg15')
         ##<--[inamura 140323]
        """
        argst1 = self.findChild(QtGui.QLabel,u"argst1")
        argtx1 = self.findChild(QtGui.QLineEdit,u"arg1")
        argst2 = self.findChild(QtGui.QLabel,u"argst2")
        argtx2 = self.findChild(QtGui.QLineEdit,u"arg2")
        argst3 = self.findChild(QtGui.QLabel,u"argst3")
        argtx3 = self.findChild(QtGui.QLineEdit,u"arg3")
        argst4 = self.findChild(QtGui.QLabel,u"argst4")
        argtx4 = self.findChild(QtGui.QLineEdit,u"arg4")
        argst5 = self.findChild(QtGui.QLabel,u"argst5")
        argtx5 = self.findChild(QtGui.QLineEdit,u"arg5")
        argst6 = self.findChild(QtGui.QLabel,u"argst6")
        argtx6 = self.findChild(QtGui.QLineEdit,u"arg6")
        argst7 = self.findChild(QtGui.QLabel,u"argst7")
        argtx7 = self.findChild(QtGui.QLineEdit,u"arg7")
        argst8 = self.findChild(QtGui.QLabel,u"argst8")
        argtx8 = self.findChild(QtGui.QLineEdit,u"arg8")
        # 引数入力のラベルとテキストボックスを登録
        self.argList = [(argst1, argtx1), 
                        (argst2, argtx2), 
                        (argst3, argtx3), 
                        (argst4, argtx4), 
                        (argst5, argtx5), 
                        (argst6, argtx6), 
                        (argst7, argtx7), 
                        (argst8, argtx8)]
        """
                        (argst9, argtx9),
                        (argst10, argtx10),
                        (argst11, argtx11),
                        (argst12, argtx12),
                        (argst13, argtx13),
                        (argst14, argtx14),
                        (argst15, argtx15)]  ##[inamura 140323]
        """
        # 戻り値テキストボックスのコントロールを取得

        #self.rettxt = self.res.GetCtrl(self.fm, 'retval')
        self.rettxt = self.findChild(QtGui.QLineEdit,u'retval')

    #############################################
    def OnSelectTree(self, evt=None):
        """
        ツリー選択イベント処理
        @param  evt イベント情報
        @retval 無し
        """
        # 選択された文字列を取得
        #text = self.tree.GetItemText(evt.GetItem())
        text = self.tree.currentItem().text(0)
        mfname = VISMODULE + '.' + text

        # 該当する関数をリストから探す
        args = None
        for func in self.rgfuncs:
            # 関数名称か
            if func.mfname == mfname:   
                args = func.args
                break
        # 登録関数でなければ
        if args == None:
            return

        # 引数をテキストボックスへ展開
        i = 0
        for arg in args:
            # 文字列とテキストボックスのコントロールを取得 
            strArg, txtArg = self.argList[i]
            # ラベルを変更 
            #strArg.SetLabel(arg.label+": ")
            strArg.setText( arg.label+": ")
            argitem = arg.value
            if arg.type == "string":
                argitem = argitem.strip('"')
                argitem = argitem.strip("'")
            
            #txtArg.SetValue(argitem)
            txtArg.setText(argitem)
            # 選択可とする
            #txtArg.Enabled(True)
            txtArg.setEnabled(True)
            # ツールチップを設定
            #tip = wx.ToolTip(arg.tip)
            #txtArg.SetToolTip(tip)
            if arg.tip.strip() == "":
                #tip.Enable(False)
                pass
            else:
                #tip.Enable(True)
                txtArg.setToolTip(u'%s'%(arg.tip.strip()))

            i += 1
                
        # 残りの引数テキストボックスをデフォルトに戻す
        while i < 8:
            strArg, txtArg = self.argList[i]
            # ラベルをデフォルトに戻す
            #strArg.SetLabel("Argument:")
            strArg.setText(u"Argument")
            # 値をクリア
            #txtArg.SetValue("")
            txtArg.setText("")
            # 選択不可とする
            #txtArg.Enable(False)
            txtArg.setEnabled(False)
            # ツールチップをクリア
            #txtArg.SetToolTip(wx.ToolTip(""))
            txtArg.setToolTip("")
            
            i += 1

        # 戻り値無しか
        if func.retn == None:
            #self.rettxt.SetValue("")
            #self.rettxt.Enable(False)
            #self.rettxt.SetToolTip(wx.ToolTip(""))
            self.rettxt.setText("")
            self.rettxt.setEnabled(False)
            self.rettxt.setToolTip("")
        else:
            #self.rettxt.SetValue(func.retn.label)
            #self.rettxt.Enable(True)
            self.rettxt.setText(u'%s'%(func.retn.label))
            self.rettxt.setEnabled(True)
            #tip = wx.ToolTip(func.retn.tip)
            #self.rettxt.SetToolTip(tip) 
            if arg.tip.strip() == "":
                #tip.Enable(False)
                pass
            else:
                #tip.Enable(True)
                self.rettxt.setToolTip(func.retn.tip)
            
        # Exec ボタンを選択可とする
        #btExec = self.res.GetCtrl(self.fm, 'btExec')  
        #btExec.Enable(True)
        self.btExec.setEnabled(True)
        
        self.func = func.Copy()         

    #############################################
    def OnExec(self):
        """
        関数をメインスレッドで実行する
        引数として、サブスレッドの戻り値を利用可
        @param  evt イベント情報
        @retval 無し
        """
        retFuncs = []
        self.lock.acquire()
        # サブスレッドで実行済み関数の戻り値を取得
        # for efunc in self.execFuncs:
        for efunc in self.parent.lineFuncs:  # 2010.01.05 Minakawa 可視化不具合対策
            # 実行結果があれば
            if efunc.retn != None and efunc.retn.retResult != None:
                # リストに入れる
                retFuncs.append(efunc)
        self.lock.release()
        # サブスレッドの結果に、可視化処理の結果を追加
        retFuncs.extend(self.retFuncs) 
       
        # テキストボックスから引数を取得
        i = 0
        execargs = []
        for arg in self.func.args:
            # テキストボックスのコントロールを取得 
            txtArg = self.argList[i][1]
            # 該当するテキストボックスの内容を取得
            #item = txtArg.GetValue().strip()
            item = txtArg.text().strip()
            # 入力値の型をチェックし、OKであれば読み込み
            if not self.rd.CheckArgType(arg, item):
                return

            # 実行形式の引数に変換
            execarg = self.rd.ChangeArg(arg, retFuncs) 

            # 正しく変換されていなければ
            if execarg == None:
                try:
                    # 引数の型が戻り値か
                    if arg.type == "retval":
                        # まだ戻り値ができていない
                        raise UtilQt.PlotException('Sequencer', 'S000', (arg.value,))
                except UtilQt.PlotException, ex:
                    #UtilPlot.PlotMessage(self.fm, ex)
                    UtilQt.PlotMessage(self, ex)
                # エラー中止
                return     
            execargs.append(execarg)
            i += 1
            
            # 戻り値があるなら
            if self.func.retn != None:
                # 戻り値を取得        
                #retlabel = self.rettxt.GetValue().strip()
                retlabel = self.rettxt.text().strip()
                try:
                    if retlabel == "":
                        raise UtilQt.PlotException('Common', 'C013', ("Return Label",))
                except UtilQt.PlotException, ex:
                    #UtilPlot.PlotMessage(self.fm, ex)
                    UtilQt.PlotMessage(self, ex)
                    # エラー中止
                    return     

        # 関数の実行
        try:
            try:            
                ret = apply(self.func.fobj, execargs)
            except:
                # 実行時エラー
                raise UtilQt.PlotException('Sequencer', 'S001', ())
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.fm, ex)
            UtilQt.PlotMessage(self, ex)
            return
             
        # 戻り値があるなら
        if self.func.retn != None:
            # 戻り値をセット        
            self.func.retn.label = retlabel
            self.func.retn.retResult = ret
            # 可視化処理の結果リストに追加
            self.retFuncs.append(self.func)
        ##[inamura 120128]-->
        ## These commands are most important role to remove memory leak
        # delete returned object
        del ret 
        # delete objects using as arguments for executing commands
        for ee in execargs:
            del ee
        ##<--[inamura 120128]

    #############################################
    def OnClose(self, evt):
        """
        画面を閉じる
        @param  evt イベント情報
        @retval 無し
        """
         # ウィンドウを非表示にする
        #self.fm.Hide()
        self.hide()
        
    #############################################
    def ShowFrame(self):
        """
        画面を閉じる
        @param  無し
        @retval 無し
        """
         # ウィンドウを非表示にする
        #self.fm.Show()
        self.show()
        

#######################################
#  CommentDialog 
#######################################     
class CommentDialog(QtGui.QDialog):
    """
    コメント入力ダイアログ
    """
    #########################################
    def __init__(self, parent, comment, cbFunc):
        """
        コンストラクタ
        @param  parent  親ウィンドウ(mainframe)のID
        @param  comment コメントの初期値  
        @param  cbFunc  コールバック関数   
        @retval 無し
        """
        self.cbFunc = cbFunc
        # リソースファイルを取得
        #res = UtilPlot.ResourceFile("Sequencer")
        super(CommentDialog, self).__init__(parent)
        # ウィンドウを取得
        #self.dg = res.GetDialog(parent, 'commentDG')
        #self.dg.SetIcon(UtilPlot.Images().GetMainIcon())
        self.dg = Ui_Dialog()
        if self.dg==None:
            return
        self.dg.setupUi( self )
        
        # テキストボックスのコントロールを取得
        #self.txt = res.GetCtrl(self.dg, 'comment')
        self.txt = self.findChild(QtGui.QTextEdit,u'comment')
        # 行毎に分解
        txtlst = comment.split("\n")
        txt = ""
        # 余分な空白、空白行等を除いて再構築

        for tline in txtlst:
            tline = tline.strip()
            if tline :
                txt = txt + tline + "\n"
        # マルチラインテキストボックスに表示
        #self.txt.SetValue(txt)
        cursor = self.txt.textCursor()
        cursor.insertText( txt )

        # ボタンのイベントハンドラ登録
        #self.dg.Bind(wx.EVT_BUTTON, self.OnOK, id=res.GetId('btOK'))
        #self.dg.Bind(wx.EVT_BUTTON, self.OnCancel, id=res.GetId('btCancel'))
        self.btOk = self.findChild(QtGui.QPushButton,u'btOk')
        self.btCancel = self.findChild(QtGui.QPushButton,u'btCancel')
        self.btOk.clicked.connect( self.OnOK )
        self.btCancel.clicked.connect( self.OnCancel )

        # ダイアログをモーダルモードにて表示
        #self.dg.ShowModal()
        self.show()

    #########################################
    def OnOK(self):
        """
        OK ボタン押下イベント処理
        @evt　　イベント
        @retval 無し
        """ 
        # コメント取得
        #comment = self.txt.GetValue()
        comment = self.txt.toPlainText()
        if comment==None:
            print "Comment = None"
        # コールバック関数の実行
        apply(self.cbFunc, (comment, ))
        # 画面を閉じる
        #self.dg.EndModal(self.dg.GetReturnCode()) #[inamura 160229]
        #self.dg.Destroy()
        self.close()
        return 
        
    #########################################
    def OnCancel(self):
        """
        Cansel ボタン押下イベント処理
        @evt　　イベント
        @retval 無し
        """ 
        #self.dg.EndModal(self.dg.GetReturnCode()) #[inamura 160229]
        #self.dg.Destroy()
        self.close()
 
#######################################
#  FacadeModule
####################################### 
class FacadeModule(object) :
    """
    ファサードモジュールクラス
    """
    #########################################
    def GetTip(self, doc, argName):
        """
        引数の説明を取得
        @param  doc  　　関数のドキュメント
        @param  argName  引数の名称
        @retval 説明
        """ 
        tip = ""
        # 1行づつに分解
        docLines = doc.split('\n')
        for line in docLines:
             # 引数の説明か
             if "@param" in line:
                  alst = line.split()
                  # 指定された引数か

                  if alst[1] == argName:
                      i = 2
                      # 説明を再構築

                      while i < len(alst):
                          tip = tip+alst[i]+" " 
                          i += 1

        return tip           

    #########################################
    def RenderRet(self, doc):
        """
        ドキュメント中の戻り値を解釈する
        @param  doc 　関数ドキュメント
        @retval 戻り値
        """ 
        ret = None
        # 1行づつに分解
        docLines = doc.split('\n')
        for line in docLines:
            # 戻り値か
            if "@retval" in line:
                # 単語に分割                            
                words =line.split()
                # retval の名称が指定されているか
                if len(words) > 1:
                    retN = words[1].strip()
                    n = line.find(retN)
                    
                    # 戻り値が指定されているか 
                    if retN != "None":
                        ret = ReturnValue()
                        ret.label = retN
                        ret.tip = line[n+len(retN):]
                break
        return ret

    #########################################
    def GetFuncDoc(self, fp):
        """ 
        関数ドキュメントを取得
        @param  fp 　ファイルポインタ
        @retval 関数ドキュメント
        """ 
        newDoc = ""
        # 1行読み込み(def ステートメントの次の行)
        line = fp.readline()
        
        # 関数ドキュメントか　
        if line and line.find('"""') > 0:
            # 先頭の空白文字と行末の改行コードを削除
            line = line.strip()
            line = line.rstrip()
            # トリプルクォーテーションの後に文字列があるか
            if len(line) > 3:
                newDoc = newDoc + line[3:]+"\n"
            # 次のトリプルクォーテーションまで読み込む
            while 1:
                line = fp.readline()
                # 後ろのトリプルクォーテーションの前にファイルが終了する場合のプロテクト
                # インポートできないはずだが、念のため
                if not line:
                    return ""
                
                # 空白、改行コードを除く
                line = line.strip()

                # ドキュメントの終了か
                if line.find('"""') >= 0:
                    # トリプルクォーテーションの前に文字列があるか
                    if line.find('"""') != 0:
                        # トリプルクォーテーションを除いて、ドキュメントに追加
                        newDoc =  newDoc + line[:-3]
                    break
                else:
                    newDoc = newDoc + line+"\n"
                    
        return newDoc          

    #########################################
    def EvaluateDic(self, line, fp):
        """
        関数登録モジュールの整合性チェック
        @param  line     キーワード　'_funcs' を含む行
        @param  fp       モジュールファイルのポインタ
        @retval True: OK  False:NG
        """ 
        n = line.find('{')
        line = line[n+1:].strip()
        retVal = True
        contFlag = True
        # ディクショナリが終わるまで
        while contFlag:
            # キー(関数名称)が取得できるまで
            while contFlag:
                strFunc = ""
                objFunc = ""
                n = line.find(':')
                if n >= 0:
                    strFunc = line[:n].strip()
                    line = line[n+1:].strip()
                    # 値(関数オブジェクト)が取得できるまで
                    while contFlag:
                        n = line.find(',')
                        if n >= 0:
                            if objFunc == "":
                                objFunc = line[:n].strip()
                            line = line[n+1:]
                            break
                        elif len(line) > 0:
                            # ディクショナリの終了か
                            n = line.find('}')
                            if n == 0:
                                contFlag = False
                                break
                            # 関数オブジェクトありか
                            elif n > 1:
                                objFunc = line[:n].strip()
                                contFlag = False
                                break
                            else:
                                objFunc = line
                        line = fp.readline().strip()
            
                elif '}' in line and not ':' in line:
                    contFlag = False
                    break
                line = fp.readline()
                # 関数名称取得済みか

                if strFunc != "":
                    # クォーテーションコードを除去    
                    strFunc = strFunc.strip('"')
                    strFunc = strFunc.strip("'")
                    # 関数名称とオブジェクトが不一致であれば 
                    if strFunc != objFunc:
                        retVal = False
                        contFlag = False
                
        return retVal   

    #########################################
    def RenderModules(self, module, mdfuncs, mdfuncs_order):
        """
        [inamura 140323]
        Render modules of facade fuction
        @param module   name of mudule
        @param mdfuncs  function dictionary of module
        @param mdfuncs_order 
        @retval function list
        """
        lstFuncs = []
        import inspect
        mdfunc_keys=mdfuncs.keys()
        mdfunc_lists = []
        if mdfuncs_order==None:
            mdfunc_keys.sort()
            for func_name in mdfunc_keys:
                mdfunc_lists.append( func_name )
        else:
            for func_name in mdfuncs_order:
                if func_name in mdfunc_keys:
                    mdfunc_lists.append( func_name )
        
        for mdfunc in mdfunc_lists:
            func = Function()
            func.mfname = module.strip()+"."+mdfunc
            defmod = __import__( module.strip() )
            deffunc = getattr( defmod, mdfunc )
            #print "SequenceEditor2 >> import ",func.mfname
            modargs = inspect.getargspec(deffunc)
            v_argnames = modargs.args
            v_argdefs  = modargs.defaults
            
            func.fobj = mdfuncs[mdfunc]
            func.fdoc = deffunc.func_doc
            
            if len(v_argnames)==0:
                func.args = []
            elif v_argdefs==None:
                print "mdfunc,v_argnames,v_argdefs=",mdfunc,v_argnames,v_argdefs
                continue
            else:
                func.args = []
                for arg_name,arg_def in zip( v_argnames, v_argdefs ):
                    arg = Argument()
                    arg.label = arg_name
                    arg.value = str(arg_def)
                    #print '### arg.label, arg.value=',arg_name,arg_def
                    #print "type(arg.label)=",type(arg.label)
                    #print "type(arg.value)=",type(arg.value)
                    if arg.label == "HISTORY":
                        arg.value = "HISTORY"
                        arg.type = "retval"
                    elif arg_def==None:
                        arg.value=self.RenderDefault(func.fdoc, arg.label)
                        arg.type="retval"
                    elif isinstance(arg_def,bool):
                        arg.type = "boolean"
                    elif isinstance(arg_def,str):
                        arg.type = "string"
                    elif isinstance(arg_def,float):
                        arg.type = "float"
                    elif isinstance(arg_def,int):
                        arg.type = "integer"
                    else:

                        try:
                            float(arg.value)
                        except:

                            arg.type = "retval"
                        else:

                            if '.' in arg.value:

                                 arg.type = "float"
                            else:
                                 arg.type = "integer"



                    arg.tip = self.GetTip(func.fdoc, arg.label)
                    # 引数を登録 
                    func.args.append(arg)

            func.retn = self.RenderRet(func.fdoc)
            
            lstFuncs.append(func)
            
        return lstFuncs
    #########################################
    def RenderDefault(self, doc, label):
        """
        [inamura 140323]
        Analysis default value for an argument from doc
        @param  doc   function document
        @param  label argument label
        @retval default value(string)
        """ 
        ret = None
        # 1行づつに分解
        docLines = doc.split('\n')
        for line in docLines:
            # 戻り値か
            if "@param" in line:
                # 単語に分割                            
                words =line.split()
                for a_word in words:
                    if a_word==label:
                        left_bra = line.find("[Def:")
                        if left_bra>0:
                            right_bra = line.find("]",left_bra)
                            if right_bra>0:
                                ret = line[(left_bra+5):right_bra]
                                break
        if ret==None:
            ret=""
        return ret

    #########################################
    def RenderFile(self, module, fp, mdfuncs):
        """
        ファサードモジュールファイルから関数文字列の行を取得
        @param  module  モジュール名称
        @param  fp       モジュールファイルのポインタ
        @param  mdfuncs  モジュールに登録されている関数のディクショナリ
        @retval 無し
        """ 
        # 関数登録用リストを準備
        lstFuncs = []
        # 1行づつ読み込む
        while 1:
            try:
                line = fp.readline()
            except:
                break    
                
            # ファイルの終わりか
            if not line:
                break
            # 関数か
            lw = line.split()
            if len(lw) > 0 and lw[0] == "def":
                # モジュールに登録されている関数中にあるか
                # 関数の名称が読み込んだ行の中にあるか
                nx = line.find("def")+3
                n0 = line.find('(')
                n1 = line.rfind(')')
                    
                if nx > 0 and nx < n0 and n0 < n1:

                    for funcName in mdfuncs:
                    
                       if line[nx:n0].strip() == funcName:

                            func = Function()
                            # モジュール名付きで、関数名を登録
                            func.mfname = module + '.' + funcName
                            # 関数のアドレスを取得

                            func.fobj = mdfuncs[funcName]
                            # 関数のドキュメントを取得

                            # (2バイトコードが含まれる可能性があるため、ここでは __doc__  は使用しない)
                            func.fdoc = self.GetFuncDoc(fp)
                            # 引数の文字列を取得
                            strarg = line[n0+1:n1].strip()
                            # 引数無しか
                            if strarg == "":
                                func.args = []
                            else: 
                                lst =  strarg.split(',')
                                # 文字列リストを解釈して引数リストを作成
                                func.args = self.RenderArg(func.fdoc, lst)
                             
                            # 関数ドキュメントより、戻り値を取得
                            func.retn = self.RenderRet(func.fdoc)

                            # 登録関数情報を作成
                            lstFuncs.append(func)
                            
            # 関数登録ディクショナリか                
            #elif "_functions" in line:
            elif "_functions" in line[:10]: ##[tito 120518]
                # 関数登録ディクショナリの評価
                if not self.EvaluateDic(line, fp):
                    raise UtilQt.PlotException('Sequencer', 'S014', (module,))
                
        # 読み込み終了
        fp.close()
        
        return lstFuncs
                      
    #########################################
    def RenderArg(self, doc, list):
        """
        文字列リストを解釈して引数リストを作成
        @param  doc   関数ドキュメント
        @param  list  文字列リスト
        @retval 引数リスト
        """  
        # 引数のリストを準備
        argsReal = []

        # 引数を登録
        for item in list:
            arg = Argument()
            # デフォルト値が指定されているか
            if '=' in item:
                strarg, defa = item.split('=')
                arg.label = strarg.strip()

                # 余分な空白を取り除き、デフォルト値とする
                arg.value = defa.strip()
                # 履歴を示す特殊引数か
                if arg.label == "HISTORY":
                    arg.value = "HISTORY"
                    arg.type = "retval"
                # 文字列かどうかを判定
                elif arg.value[0] == '"'  or arg.value[0] == "'" :
                    # 文字列の前後の引用符を取り除く
                    arg.value = arg.value.strip("'")
                    arg.value = arg.value.strip('"')
                    # 属性を文字列に設定
                    arg.type = "string"
                    # ブーリアン変数か
                elif arg.value == "True" or arg.value == "False":
                    arg.type = "boolean"
                else:
                    # 数値か
                    try:
                        float(arg.value)
                    except:
                        # 文字列、ブーリアン、数値以外は戻り値と仮定
                        arg.type = "retval"
                    else:
                        # 小数点があれば
                        if '.' in arg.value:
                             # 実数とする
                             arg.type = "float"
                        else:
                             arg.type = "integer"
                                           
            # デフォルト値の指定が無い場合            
            else:
                if "HISTORY" in item:
                    arg.label = "HISTORY"
                    arg.type = "retval"
                    arg.value = "HISTORY"
                else:
                    arg.value = "" 
                    arg.type = "retval"
                    arg.label = item.strip()

            # 説明を取得
            arg.tip = self.GetTip(doc, arg.label)
            # 引数を登録 
            argsReal.append(arg)

        return argsReal

    #########################################
    def GetFuncs(self, module):
        """
        スクリプトを開き、登録されている
        関数を解析して関数のリストを返す
        @param  module スクリプトのモジュール名
        @retval 登録関数リスト
        """ 
        
        
        # スクリプトファイル名を作る
        pyfile = module + ".py"
        
        fullPath = UtilQt.AcqPath().GetModulePath(pyfile)
        #print fullPath ##[inamrua 140323]
        
        if fullPath == None: 

            # 環境変数PYTHONPATHに指定されたディレクトリを取得
            paths = str(os.environ.get('PYTHONPATH')).split(os.pathsep)
            #print paths ##[inamrua 140323]
            # 全PYTHONPATHディレクトリを探索
            for path in paths:
                fpath = os.path.normpath(os.path.join(path, pyfile))

                # ディレクトリに目的ファイルがあるか
                if os.path.isfile(fpath):
                    # フルパスを確定
                    fullPath = fpath
                    break
        # 指定されたファイルが、Python Path 中に無ければ
        if fullPath == None:
            # 空白を入力していない場合

            if len(module.strip()) > 0:
                raise UtilQt.PlotException('Sequencer', 'S009', (module,))
                return
            else:
                return None

        else:
            mdfuncs = {}
            # モジュールをインポートし、関数ディクショナリと、モジュールの属性を取得
            try:
                # 文字列を、インポート用の変数に変換してインポート
                mod = __import__(module)
            except:
                # インポート不可のメッセージ表示
                raise UtilQt.PlotException('Sequencer', 'S008', (module,))
            try:        
                # 関数登録ディクショナリを取得
                mdfuncs = mod._functions
            except:
                # 関数登録用ディクショナリが無い  
                raise UtilQt.PlotException('Sequencer', 'S010', (module,))

            # 登録されている関数が無い場合は
            ##[inamura 140323]-->
            mdfuncs_order = None
            try:
                mdfuncs_order = mod._functionsOrder
            except:
                pass
            """
            if len(mdfuncs) == 0:
                return []
            # スクリプトファイルを開く
            try: 
                fp = codecs.open(fullPath, 'r', "utf-8")     
            except:
                # ファイルが開けない
                raise UtilQt.PlotException('Common', 'C006', (fullPath,))
            """
            ##<--[inamura 140323]
            # スクリプトファイルを解析し、登録されている関数のリストを作って返す
            try:
                #funcs = self.RenderFile(module, fp, mdfuncs)
                funcs = self.RenderModules(module,mdfuncs,mdfuncs_order) ##[inamura 140323]
            except:
                # 解析中に何かエラーがあった
                raise
           
            return funcs
        
        
#######################################
#  SequenceEditor
####################################### 
class SequenceEditor(QtGui.QMainWindow) :
    """
    解析シーケンサのメインフレーム
    """
    # シーケンスの実行状態定義
    ##[inamura 120403]-->
    STATUS = {-1: "Inexecutable",
               0: "Executable",
               1: "Executing Command(s)",
               2: "Waiting to Stop (Editable)",
               3: "Waiting to Stop (Not Editable)",
               4: "Resuming from Stop"}
    ##<--[inamura 120403]

    
    #########################################
    def __init__(self, modules):
        """
        メインフレームのコンストラクタ
        @param  modules  インポート対象のモジュールのリスト 
        @retval 無し
        """ 
        # 初期化
        super(SequenceEditor, self).__init__(None)
        self.modules = modules
        self.vis = None
        self.statNo = -1
        self.activeFnc = None
        self.lineFuncs = []
        # 測定シーケンスか 
        if modules[0] =='0':
            # 起動元から渡された認証情報を設定
            AH.SetAuthenticInfo(modules[1],modules[2]) 
            modules = modules[3:]
            self.acqF = True
        else:
            self.acqF = False
        
        # シーケンス排他制御用のロックを作る
        self.lock = thread.allocate_lock()
        
        # 画面作成
        #self.res = UtilPlot.ResourceFile("Sequencer")
        #self.res = UtilPlot.ResourceFile("Sequencer2") ##[inamura 140323]
        #self.frame = self.res.GetFrame(None, 'mainframe')
        self.frame = Ui_MainWindow()
        if self.frame == None:
            return
        #self.frame.SetIcon(UtilPlot.Images().GetMainIcon())
        self.frame.setupUi( self )
        
        if self.acqF:
            self.frameTitle = "Measuring Sequence"
        else:
            # タイトル文字列を取得
            #self.frameTitle = self.frame.GetTitle()
            self.frameTitle = self.windowTitle()
            
        # タイトルに、ファイル名を付加(最初は New)
        #self.frame.SetTitle(self.frameTitle+ " - New")
        self.setWindowTitle(self.frameTitle+ " - New")

        # 各クラスのインスタンスを取得
        self.execC = ExecSequence(self.lock)
        #self.sfile = SequenceFile(self.frame)
        #self.rd = Rendering(self.frame)
        self.sfile = SequenceFile(self)
        self.rd = Rendering(self)
        
        # 各種コントロールの取得とイベントハンドラのセット
        self.SetControls()

        # リストコントロールにイメージリストを登録
        #images = wx.ImageList(20, 20, True)
        #images.Add(UtilPlot.Images().GetBmp("Red"))        # 0
        #images.Add(UtilPlot.Images().GetBmp("Green"))      # 1
        #images.Add(UtilPlot.Images().GetBmp("Processing")) # 2
        #images.Add(UtilPlot.Images().GetBmp("GreenEnd"))   # 3
        #images.Add(UtilPlot.Images().GetBmp("RedEnd"))     # 4
        #self.list1.AssignImageList(images, wx.IMAGE_LIST_SMALL)
        self.statusImage = [None,None,None,None,None]
        #self.statusImage[0] = UtilPlot.ImagesXpm().GetQPixmap( "Red" )
        #self.statusImage[1] = UtilPlot.ImagesXpm().GetQPixmap( "Green" )
        #self.statusImage[2] = UtilPlot.ImagesXpm().GetQPixmap( "Processing" )
        #self.statusImage[3] = UtilPlot.ImagesXpm().GetQPixmap( "GreenEnd" )
        #self.statusImage[4] = UtilPlot.ImagesXpm().GetQPixmap( "RedEnd" )
        self.statusImage[0] = UtilQt.ImagesXpm().GetQPixmap( "Red" )
        self.statusImage[1] = UtilQt.ImagesXpm().GetQPixmap( "Green" )
        self.statusImage[2] = UtilQt.ImagesXpm().GetQPixmap( "Processing" )
        self.statusImage[3] = UtilQt.ImagesXpm().GetQPixmap( "GreenEnd" )
        self.statusImage[4] = UtilQt.ImagesXpm().GetQPixmap( "RedEnd" )

        # リストのタイトル行を表示
        #self.list1.InsertColumn(0, "Sequence", wx.LIST_FORMAT_LEFT)
        #self.list1.InsertColumn(1, "Begin Time", wx.LIST_FORMAT_LEFT)
        #self.list1.InsertColumn(2, "End Time", wx.LIST_FORMAT_LEFT)
        self.list1.setColumnCount(3)
        self.list1.setHeaderLabels(["Sequence","Begin Time","End Time"])
        
        # カラムの幅を設定    
        #self.list1.SetColumnWidth(0, 360)
        #self.list1.SetColumnWidth(0, 520) ##[inamura 101228]
        #self.list1.SetColumnWidth(0, 640) ##[inamura 130323]
        #self.list1.SetColumnWidth(1, 80)
        #self.list1.SetColumnWidth(2, 80)
        #self.list1.setColumnWidth(0, 20)
        self.list1.setColumnWidth(0, 640)
        self.list1.setColumnWidth(1, 80)
        self.list1.setColumnWidth(2, 80)

        # 登録されている関数の一覧をツリー表示
        self.rgfuncs = FunctionTree(self.frame).MakeNode(self.tree, "Functions", modules)

        # 画面表示を初期化
        self.ChangeBtnStatus()
        # メインフレーム画面の表示
        #self.frame.Show()
        self.show()
        
        self.LoadInitSequence() ##[inamura 120321]
        
        ##[inamura 160220]-->
        dt = datetime.datetime.now()
        tmp_LogFile = BASELOGFILE%(dt.strftime("%Y%m%d%H%M%S"),os.getpid())
        self.LogFile = None
        try:
            tmp_LogFile = os.path.join( os.environ["UTSUSEMI_USR_PRIV_HOME"], "ana","tmp",tmp_LogFile )
            ff=open( tmp_LogFile, "w" )
            ff.write( "[%s] SequenceEditor start\n"%( dt.strftime("%Y%m%d%H%M%S") ) )
            ff.close()
            self.LogFile = tmp_LogFile
        except:
            print "### Failed making LogFile as "+tmp_LogFile
            self.LogFile = None
        self.execC.SetLogFileName( self.LogFile )
        ##<--[inamura 160220]
        #self.currentDirTxt.SetLabel( os.getcwd() ) ##[inamura 160822]
        self.currentDirTxt.setText( os.getcwd() )

    #########################################
    def SetControls(self):
        """
        各種イコントロールの取得とベントハンドラの登録
        @param  無し 
        @retval 無し
        """ 
        # リソースからツリーコントロールとリストコントロールを取得     
        #self.tree = self.res.GetCtrl(self.frame, 'tree0')
        #self.list1 = self.res.GetCtrl(self.frame, 'list1')
        self.tree = self.findChild(QtGui.QTreeWidget, u'tree0')
        self.list1 = self.findChild(QtGui.QTreeWidget, u'list1')
        self.list1.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection )

        ##[inamura 110111]-->
        ##[inamura 101228]-->
        # 予約語入力テキストボックスのコントロール取得
        """
        panel = self.res.GetCtrl(self.frame, 'panel')
        runtx1 = self.res.GetCtrl(panel, 'runno1')
        runtx2 = self.res.GetCtrl(panel, 'runno2')
        runtx3 = self.res.GetCtrl(panel, 'runno3')
        runtx4 = self.res.GetCtrl(panel, 'runno4')
        deftx1 = self.res.GetCtrl(panel, 'deftx1')
        deftx2 = self.res.GetCtrl(panel, 'deftx2')
        deftx3 = self.res.GetCtrl(panel, 'deftx3')
        deftx4 = self.res.GetCtrl(panel, 'deftx4')
        """
        # 測定シーケンスなら
        """
        if self.acqF:
            # Run No. を選択不可とする
            runtx1.Enable(False)
            runtx2.Enable(False)
            runtx3.Enable(False)
            runtx4.Enable(False)
        """
        # ディクショナリへ設定
        """
        self.reserved = {"RUN1":runtx1, 
                         "RUN2":runtx2, 
                         "RUN3":runtx3, 
                         "RUN4":runtx4, 
                         "DEF1":deftx1, 
                         "DEF2":deftx2,
                         "DEF3":deftx3,
                         "DEF4":deftx4}
        """
        #panel = self.res.GetCtrl(self.frame, 'panel')
        self.reserved = {}
        ##<--[inamura 101228]
        ##<--[inamura 110111]
        ##[inamura 110105]-->
        #splash_path = os.path.join( os.environ['UTSUSEMI_BASE_DIR'],'ana/Reduction/','LOGO_utsusemi2_s.png' )
        splash_path = os.path.join( os.environ['UTSUSEMI_BASE_DIR'],'ana/Reduction/','LOGO_utsusemi_3_c_long.png' )
        if os.path.exists( splash_path ):
            #splash_panel = self.res.GetCtrl(self.frame, 'SplashPanel' )
            #splash_bmp = wx.Image(splash_path).ConvertToBitmap()
            #wx.StaticBitmap(splash_panel, -1, splash_bmp, (2,0),(300,50))
            splash_panel = self.findChild(QtGui.QLabel,u'SplashPanel')
            splash_panel.setPixmap( QtGui.QPixmap( splash_path ) )
            splash_panel.setAlignment(QtCore.Qt.AlignCenter)
        ##<--[inamura 110105]
        
        # 関数ドキュメント表示用テキストボックスのコントロールを取得
        #self.fdocTxt = self.res.GetCtrl(panel, 'funcdoc')
        self.fdocTxt = self.findChild( QtGui.QTextBrowser, u'funcdoc' )
        self.fdocTxt.setLineWrapColumnOrWidth(800)
        self.fdocTxt.setLineWrapMode(QtGui.QTextEdit.FixedPixelWidth)
        
        # 引数文字列とテキストボックスのコントロールを取得
        """
        argpanel = self.res.GetCtrl(self.frame, 'argpanel')
        argst1 = self.res.GetCtrl(argpanel, 'argst1')
        argtx1 = self.res.GetCtrl(argpanel, 'arg1')
        argst2 = self.res.GetCtrl(argpanel, 'argst2')
        argtx2 = self.res.GetCtrl(argpanel, 'arg2')
        argst3 = self.res.GetCtrl(argpanel, 'argst3')
        argtx3 = self.res.GetCtrl(argpanel, 'arg3')
        argst4 = self.res.GetCtrl(argpanel, 'argst4')
        argtx4 = self.res.GetCtrl(argpanel, 'arg4')
        argst5 = self.res.GetCtrl(argpanel, 'argst5')
        argtx5 = self.res.GetCtrl(argpanel, 'arg5')
        argst6 = self.res.GetCtrl(argpanel, 'argst6')
        argtx6 = self.res.GetCtrl(argpanel, 'arg6')
        argst7 = self.res.GetCtrl(argpanel, 'argst7')
        argtx7 = self.res.GetCtrl(argpanel, 'arg7')
        argst8 = self.res.GetCtrl(argpanel, 'argst8')
        argtx8 = self.res.GetCtrl(argpanel, 'arg8')
        ##[inamura 140323]-->
        argst9 = self.res.GetCtrl(argpanel, 'argst9')
        argtx9 = self.res.GetCtrl(argpanel, 'arg9')
        argst10 = self.res.GetCtrl(argpanel, 'argst10')
        argtx10 = self.res.GetCtrl(argpanel, 'arg10')
        argst11 = self.res.GetCtrl(argpanel, 'argst11')
        argtx11 = self.res.GetCtrl(argpanel, 'arg11')
        argst12 = self.res.GetCtrl(argpanel, 'argst12')
        argtx12 = self.res.GetCtrl(argpanel, 'arg12')
        argst13 = self.res.GetCtrl(argpanel, 'argst13')
        argtx13 = self.res.GetCtrl(argpanel, 'arg13')
        argst14 = self.res.GetCtrl(argpanel, 'argst14')
        argtx14 = self.res.GetCtrl(argpanel, 'arg14')
        argst15 = self.res.GetCtrl(argpanel, 'argst15')
        argtx15 = self.res.GetCtrl(argpanel, 'arg15')
        ##<--[inamura 140323]
        """
        argst1 = self.findChild(QtGui.QLabel,u"argst1")
        argtx1 = self.findChild(QtGui.QLineEdit,u"arg1")
        argst2 = self.findChild(QtGui.QLabel,u"argst2")
        argtx2 = self.findChild(QtGui.QLineEdit,u"arg2")
        argst3 = self.findChild(QtGui.QLabel,u"argst3")
        argtx3 = self.findChild(QtGui.QLineEdit,u"arg3")
        argst4 = self.findChild(QtGui.QLabel,u"argst4")
        argtx4 = self.findChild(QtGui.QLineEdit,u"arg4")
        argst5 = self.findChild(QtGui.QLabel,u"argst5")
        argtx5 = self.findChild(QtGui.QLineEdit,u"arg5")
        argst6 = self.findChild(QtGui.QLabel,u"argst6")
        argtx6 = self.findChild(QtGui.QLineEdit,u"arg6")
        argst7 = self.findChild(QtGui.QLabel,u"argst7")
        argtx7 = self.findChild(QtGui.QLineEdit,u"arg7")
        argst8 = self.findChild(QtGui.QLabel,u"argst8")
        argtx8 = self.findChild(QtGui.QLineEdit,u"arg8")
        argst9 = self.findChild(QtGui.QLabel,u"argst9")
        argtx9 = self.findChild(QtGui.QLineEdit,u"arg9")
        argst10 = self.findChild(QtGui.QLabel,u"argst10")
        argtx10 = self.findChild(QtGui.QLineEdit,u"arg10")
        argst11 = self.findChild(QtGui.QLabel,u"argst11")
        argtx11 = self.findChild(QtGui.QLineEdit,u"arg11")
        argst12 = self.findChild(QtGui.QLabel,u"argst12")
        argtx12 = self.findChild(QtGui.QLineEdit,u"arg12")
        argst13 = self.findChild(QtGui.QLabel,u"argst13")
        argtx13 = self.findChild(QtGui.QLineEdit,u"arg13")
        argst14 = self.findChild(QtGui.QLabel,u"argst14")
        argtx14 = self.findChild(QtGui.QLineEdit,u"arg14")
        argst15 = self.findChild(QtGui.QLabel,u"argst15")
        argtx15 = self.findChild(QtGui.QLineEdit,u"arg15")

        #self.rettxt = self.res.GetCtrl(argpanel, 'retval')
        self.rettxt = self.findChild(QtGui.QLineEdit, u'retval')
        
        # 引数入力のラベルとテキストボックスを登録
        self.argList = [(argst1, argtx1), 
                        (argst2, argtx2), 
                        (argst3, argtx3), 
                        (argst4, argtx4), 
                        (argst5, argtx5), 
                        (argst6, argtx6), 
                        (argst7, argtx7), 
                        (argst8, argtx8),
                        (argst9, argtx9),
                        (argst10, argtx10),
                        (argst11, argtx11),
                        (argst12, argtx12),
                        (argst13, argtx13),
                        (argst14, argtx14),
                        (argst15, argtx15)] ##[inamura 140323]

        # ステータス表示ラベルのコントロールを取得
        #stpanel = self.res.GetCtrl(self.frame, 'stpanel') ##[inamura 120403]
        #self.statTxt = self.res.GetCtrl(stpanel, 'status')##[inamura 120403]
        #self.statTxt = self.res.GetCtrl(panel, 'status')
        #self.currentDirTxt = self.res.GetCtrl(panel, 'stCurrentDir' ) ##[inamura 160822]
        self.statTxt = self.findChild(QtGui.QLabel,u'status')
        self.currentDirTxt = self.findChild(QtGui.QLabel,u'stCurrentDir')
        
        # ボタンのコントロールを取得
        """
        self.btBegin = self.res.GetCtrl(panel, 'btBegin')
        self.btStop = self.res.GetCtrl(panel, 'btStop')
        self.btResume = self.res.GetCtrl(panel, 'btResume')
        self.btOpen = self.res.GetCtrl(panel, 'btOpen')
        self.btClear = self.res.GetCtrl(panel, 'btClear')
        self.btAdd = self.res.GetCtrl(panel, 'btAdd')
        self.btSaveas = self.res.GetCtrl(panel, 'btSaveas')
        self.btUp = self.res.GetCtrl(panel, 'btUp')
        self.btDown = self.res.GetCtrl(panel, 'btDown')
        self.btCopyAdd = self.res.GetCtrl(panel, 'btCopyAdd') ##[inamura 101228]
        self.btCopyAdd.Enable(False) ##[inamura 101228]
        self.btRemove = self.res.GetCtrl(panel, 'btRemove') ##[inamura 120403]
        self.btCCD = self.res.GetCtrl(panel, 'btCCD') ##[inamura 160822]
        """
        self.btBegin = self.findChild(QtGui.QPushButton,u'btBegin')
        self.btStop = self.findChild(QtGui.QPushButton,u'btStop')
        self.btResume = self.findChild(QtGui.QPushButton,u'btResume')
        self.btOpen = self.findChild(QtGui.QPushButton,u'btOpen')
        self.btClear = self.findChild(QtGui.QPushButton,u'btClear')
        self.btAdd = self.findChild(QtGui.QPushButton,u'btAdd')
        self.btSaveas = self.findChild(QtGui.QPushButton,u'btSaveas')
        self.btUp = self.findChild(QtGui.QPushButton,u'btUp')
        self.btDown = self.findChild(QtGui.QPushButton,u'btDown')
        self.btCopyAdd = self.findChild(QtGui.QPushButton,u'btCopyAdd')
        self.btCopyAdd.setEnabled(False)
        self.btCCD = self.findChild(QtGui.QPushButton,u'btCCD')
        self.btRemove= self.findChild(QtGui.QPushButton,u'btRemove')
        self.btSet   = self.findChild(QtGui.QPushButton,u'btSet')
        self.btVis   = self.findChild(QtGui.QPushButton,u'btVis')
        
        btAdd_icon = self.btAdd.style().standardIcon(QtGui.QStyle.SP_ArrowRight)
        btRemove_icon = self.btRemove.style().standardIcon(QtGui.QStyle.SP_TrashIcon)
        btOpen_icon = self.btOpen.style().standardIcon(QtGui.QStyle.SP_DialogOpenButton)
        btSaveas_icon = self.btSaveas.style().standardIcon(QtGui.QStyle.SP_DialogSaveButton)
        btUp_icon = self.btUp.style().standardIcon(QtGui.QStyle.SP_ArrowUp)
        btDown_icon = self.btDown.style().standardIcon(QtGui.QStyle.SP_ArrowDown)
        btCopyAdd_icon = self.btCopyAdd.style().standardIcon(QtGui.QStyle.SP_BrowserReload)
        self.btAdd.setIcon(btAdd_icon)
        self.btRemove.setIcon(btRemove_icon)
        self.btOpen.setIcon(btOpen_icon)
        self.btSaveas.setIcon(btSaveas_icon)
        self.btUp.setIcon(btUp_icon)
        self.btDown.setIcon(btDown_icon)
        self.btCopyAdd.setIcon(btCopyAdd_icon)
        
        # 実行中に選択不可とするボタンのコントロールを取得
        #self.bttns = [ self.res.GetCtrl(panel, 'btApply'),
        """
        self.bttns = [ self.res.GetCtrl(panel, 'btAdd'),
                       self.res.GetCtrl(panel, 'btRemove'),
                       self.res.GetCtrl(panel, 'btOpen'),
                       self.res.GetCtrl(panel, 'btSaveas'),
                       self.res.GetCtrl(panel, 'btClear'),
                       self.res.GetCtrl(argpanel, 'btSet'),
                       self.res.GetCtrl(panel,'btUp'),
                       self.res.GetCtrl(panel,'btDown'),
                       self.res.GetCtrl(panel,'btCopyAdd')]  ##[inamura 120403]
        """
        self.bttns = [ self.btAdd,
                       self.btRemove,
                       self.btOpen,
                       self.btSaveas,
                       self.btClear,
                       self.btSet,
                       self.btUp,
                       self.btDown,
                       self.btCopyAdd ]

        # ボタンのイベントハンドラ登録
        """
        self.frame.Bind(wx.EVT_BUTTON, self.OnApply, id=self.res.GetId('btApply'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnAdd, id=self.res.GetId('btAdd'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnRemove, id=self.res.GetId('btRemove'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnBegin, id=self.res.GetId('btBegin'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnStop, id=self.res.GetId('btStop'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnResume, id=self.res.GetId('btResume'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnOpen, id=self.res.GetId('btOpen'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnVisualize, id=self.res.GetId('btVis'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnSaveas, id=self.res.GetId('btSaveas'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnClear, id=self.res.GetId('btClear'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnSet, id=self.res.GetId('btSet'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnUp, id=self.res.GetId('btUp'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnDown, id=self.res.GetId('btDown'))
        self.frame.Bind(wx.EVT_BUTTON, self.OnCopyAdd, id=self.res.GetId('btCopyAdd')) ##[inamura 101228]
        self.frame.Bind(wx.EVT_BUTTON, self.OnChangeCurrentDir, id=self.res.GetId('btCCD') )##[inamura 160822]
        """
        #self.btApply.clicked.connect(self.OnApply)
        self.btAdd.clicked.connect(self.OnAdd)
        self.btRemove.clicked.connect(self.OnRemove)
        self.btBegin.clicked.connect(self.OnBegin)
        self.btStop.clicked.connect(self.OnStop)
        self.btResume.clicked.connect(self.OnResume)
        self.btOpen.clicked.connect(self.OnOpen)
        self.btVis.clicked.connect(self.OnVisualize)
        self.btSaveas.clicked.connect(self.OnSaveas)
        self.btClear.clicked.connect(self.OnClear)
        self.btSet.clicked.connect(self.OnSet)
        self.btUp.clicked.connect(self.OnUp)
        self.btDown.clicked.connect(self.OnDown)
        self.btCopyAdd.clicked.connect(self.OnCopyAdd)
        self.btCCD.clicked.connect(self.OnChangeCurrentDir)

        # リスト選択時のイベントハンドラ登録
        #self.frame.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnSelect, id=self.res.GetId('list1'))
        #self.frame.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnDeselectedList, id=self.res.GetId('list1')) ##[inamura 120424]
        self.list1.itemSelectionChanged.connect( self.OnSelect )
        self.LIST1_UNSELECTED = -1
        self.LIST1_EXECUTED = -999999
        self.list1_selected = self.LIST1_UNSELECTED

        # ツリー選択イベントの登録
        #self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectTree, self.tree)
        self.tree.itemSelectionChanged.connect( self.OnSelectTree )
        
        #クローズイベント登録
        #self.frame.Bind(wx.EVT_CLOSE, self.OnClose)
 
    #########################################
    def ChangeStepsStatus(self):
        """
        実行可能であれば、Begin ボタンを選択可とする
        @param  無し
        @retval 無し
        """ 

        # リストの行数を取得
        #nLine = self.list1.GetItemCount()
        nLine = self.list1.topLevelItemCount()

        lstRet = []
        bgflag = True
        # 登録されている全行を調べる
        for i in range(nLine):

            # 関数データを作成
            func = self.lineFuncs[i]
            flag = True

            for arg in func.args:
                # 先行関数の戻り値を引数としてとるか
                if arg.type == "retval":
                    if arg.label != "HISTORY":
                        # 先行する関数の戻り値として指定されていなければ
                        if not arg.value in lstRet:
                            flag = False
                # その他の引数で、値がなければ    
                elif arg.value == "" or arg.value == '""':
                    flag = False
            # 引数エラー無しか
            if flag:

                # 結果無しであれば
                if func.stat <= 0:
                    # 緑信号イメージを表示
                    #self.list1.SetItemImage(i, 1)
                    #self.list1.SetStringItem(i, 1,"")
                    #self.list1.SetStringItem(i, 2,"")
                    self.list1.topLevelItem(i).setIcon(0, self.statusImage[1] )
                    self.list1.topLevelItem(i).setText(1,"")
                    self.list1.topLevelItem(i).setText(2,"")
                    func.stat = 0
            # 引数エラーがあれば
            else:
                
                # 赤信号イメージを表示
                #self.list1.SetItemImage(i, 0)
                #self.list1.SetStringItem(i, 1,"")
                #self.list1.SetStringItem(i, 2,"")
                self.list1.topLevelItem(i).setIcon(0, self.statusImage[0] )
                self.list1.topLevelItem(i).setText(1,"")
                self.list1.topLevelItem(i).setText(2,"")
                func.ClearResult()
                func.stat = -1
                bgflag = False
            
            # 戻り値があれば 
            if func.retn != None:
                # 戻り値を登録
                lstRet.append(func.retn.label)
        try:
            # Waiting to Resume 中であれば
            if self.statNo == 4:
                # 要求解除のワーニングを表示
                raise UtilQt.PlotException('Sequencer', 'S002', ())
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            
        # Resumption Bookable または Resumption Booked であれば
        if self.statNo >= 2:
            if bgflag:
                # 状態変更(→ Resumption Bookable)
                self.statNo = 2
            else:
                # 状態変更(→ Resumption NOT Bookable)
                self.statNo = 3
        # Ready または Not Ready であれば
        else:
            #if bgflag and self.list1.GetItemCount():
            if bgflag and self.list1.topLevelItemCount():
                # 状態変更(→ Ready)
                self.statNo = 0
            else:
                # 状態変更(→ Not Ready)
                self.statNo = -1

        # 状態変更後の処理
        self.ChangeBtnStatus()

    #########################################
    def OnApply(self, evt=None):
        """
        Apply ボタン押下イベント処理
        予約語テキストボックスを実行関数リストに適用する
        @param evt　　イベント
        @retval 無し
        """
        self.lock.acquire() 
        # シーケンスを調べる
        i = 0
        for func in self.lineFuncs:
            # 予約語を、テキストボックスから取得した値に置き換える
            if self.CheckReserved(func.args):
                # 変更したステップの影響が及ぶステップの結果をクリア
                self.rd.CheckBackwash(i, self.lineFuncs)
                # 変更した関数の結果をクリア
                func.ClearResult()
            # 表示行を作る
            strLine = self.rd.MakeLine(func)
            # 表示を置き換え
            #self.list1.SetStringItem(i, 0, strLine)
            self.list1.topLevelItem(i).setText(0,strLine)
            i += 1
        
        # Begin ボタンの選択可/不可を設定
        self.ChangeStepsStatus()
        # 選択行の内容を、テキストボックスへ反映
        self.OnSelect()
        self.list1_selected = self.LIST1_UNSELECTED
        self.lock.release()

    #########################################
    def OnAdd(self, evt=None):
        """
        Add ボタン押下イベント処理
        関数を実行リストに追加
        @param evt　　イベント
        @retval 無し
        """
        # 関数が選択されていなければ何もしない
        if self.activeFnc == None:
            return
        # 引数と戻り値をデフォルトに戻す
        func = self.activeFnc.Copy()
        self.lock.acquire()
        self.lineFuncs.append(func)
        
        # リストに1行追加、テキストボックスに値を設定
        self.SetTxt(func)
        # Begin ボタンの選択可/不可を設定
        self.list1_selected=self.LIST1_UNSELECTED
        self.ChangeStepsStatus()
        self.lock.release()
 
    #########################################
    def SetTxt(self, func):
        """
        テキストボックスに値を設定
        予約語をテキストボックスの内容に置き換える
        @param func　　関数データ
        @retval 無し
        """
        # リストの行数を取得
        #nLine = self.list1.GetItemCount()
        nLine = self.list1.topLevelItemCount()
        # 予約語を、テキストボックスから取得した値に置き換える
        self.CheckReserved(func.args)

        # 表示する文字列を作成
        strLine = self.rd.MakeLine(func)
        #　リストに1行を追加
        #index = self.list1.InsertStringItem(1000, strLine)
        new_line = QtGui.QTreeWidgetItem()
        new_line.setText(0,strLine)
        self.list1.addTopLevelItem( new_line )
        # 先に選択されていた行を非選択状態にする
        #index = self.list1.GetFirstSelected()
        #if index >= 0:
        #    self.list1.Select(index, False)
        index = self.list1.currentItem()
        #if index!=None:
        if isinstance(index,QtGui.QTreeWidgetItem):
            self.list1.selectionModel().clearSelection()

        # 追加した行を選択状態とする
        #self.list1.Select(nLine, True)
        self.list1.setCurrentItem( self.list1.topLevelItem( nLine ) )
        #self.list1_selected = self.LIST1_UNSELECTED
        
    #########################################
    def CheckReserved(self, args):
        """
        引数が予約語であれば、テキストボックス
        から値を取得
        @param args　　引数リスト
        @retval True: 置き換えあり、False: 置き換え無し
        """
        retval = False
        for arg in args:
            # 予約語として登録されているか
            try:
                txtcont = self.reserved[arg.label]
            except:
                pass
            else:
                # 該当するテキストボックスの値を取得
                #value = txtcont.GetValue().strip()
                value = txtcont.text().strip()
                # テキストボックスが空ではなく、前と異なっていれば
                if value != "" and arg.value != value:
                    # 引数のタイプを判定し、OKであれば入れ替え
                    retval = self.rd.CheckArgType(arg, value)

        return retval

    ##########################################
    def OnSelect(self, evt=None) :
        """
        リスト選択イベントハンドラ
        @param  evt イベント情報
        @retval 無し
        """
        #self.btUp.Enable(False)
        #self.btDown.Enable(False)
        #self.btCopyAdd.Enable(False) ##[inamura 120403]
        #self.btRemove.Enable(False) ##[inamura 120424]
        self.btUp.setEnabled(False)
        self.btDown.setEnabled(False)
        self.btCopyAdd.setEnabled(False)
        self.btRemove.setEnabled(False)
        # 選択されている行を取得    
        #index = self.list1.GetFirstSelected()
        #i = self.list1.GetItemCount()
        item = self.list1.currentItem()
        index = self.list1.indexOfTopLevelItem( item )
        i = self.list1.topLevelItemCount()

        if index < 0: ##[inamrua 120403]
            return    ##[inamura 120403]

        if self.list1_selected == index or self.list1_selected==self.LIST1_EXECUTED:
            self.OnDeselectedList()
            self.list1_selected = self.LIST1_UNSELECTED
            return
        else:
            self.list1_selected = index
        
        if self.statNo <= 0:  # "Inexecutable","Executable"を表示中のとき
            if index != 0:  # 選択行が最上部の行でなければ
                #self.btUp.Enable(True)
                self.btUp.setEnabled(True)
            if index != i-1: # 選択行が最下部の行でなければ
                #self.btDown.Enable(True)
                self.btDown.setEnabled(True)
        
        ##[inamura 120404]-->
        if (self.statNo !=1) and (self.statNo !=4):
            #self.btCopyAdd.Enable(True)
            #self.btRemove.Enable(True)  ##[inamura 120424]
            self.btCopyAdd.setEnabled(True)
            self.btRemove.setEnabled(True)
            
        if (self.statNo ==2) or (self.statNo==3): # not executing
            if self.lineFuncs[index].stat<=0: #選択コマンドが未実行で
                #選択行が最上部ではなく、一つ前のコマンドが未実行なら
                if ( index !=0 ) and ( self.lineFuncs[index-1].stat==0 ): 
                    #self.btUp.Enable(True)
                    self.btUp.setEnabled(True)
                #選択行が最終行でなければ
                if index != i-1:
                    #self.btDown.Enable(True)
                    self.btDown.setEnabled(True)
        ##<--[inamura 120404]
        
        #item = self.list1.GetItem(index)
        # 選択行の関数を取得
        func = self.lineFuncs[index]
        i = 0
        for arg in func.args:
            # 文字列とテキストボックスのコントロールを取得 
            strArg, txtArg = self.argList[i]

            if arg.label != "HISTORY":
            
                # ラベルを変更 
                #strArg.SetLabel(arg.label+": ")
                strArg.setText(arg.label+": ")
                argitem = arg.value
                if arg.type == "string":
                    argitem = argitem.strip('"')
                    argitem = argitem.strip("'")

                
                #txtArg.SetValue(argitem)
                txtArg.setText(argitem)
                ##[inamura 120404]-->
                if (self.statNo==1) or (self.statNo==4):
                    #txtArg.Enable(False)
                    txtArg.setEnabled(False)
                else:
                    # 選択可とする
                    #txtArg.Enable(True)
                    txtArg.setEnabled(True)
                ##<--[inamura 120404]
                # ツールチップを設定
                #tip = wx.ToolTip(arg.tip)
                #txtArg.SetToolTip(tip) 
                if arg.tip.strip() == "":
                    #tip.Enable(False)
                    pass
                else:
                    #tip.Enable(True)
                    txtArg.setToolTip(arg.tip.strip())
                i += 1
                # 引数の数が8個を超えるか
                try:
                    #if i > 8:
                    if i > len(self.argList):  ##[inamura 140323]
                        raise UtilQt.PlotException('Sequencer', 'S007', (func.mfname,))
                except UtilQt.PlotException, ex:
                    #UtilPlot.PlotMessage(self.frame, ex)
                    UtilQt.PlotMessage(self, ex)
                    break
                    
                
        # 残りの引数テキストボックスをデフォルトに戻す
        #while i < 8:
        while i < len(self.argList):  ##[inamura 140323]
            strArg, txtArg = self.argList[i]
            # ラベルをデフォルトに戻す
            #strArg.SetLabel("Argument:")
            strArg.setText("Argument:")
            # 値をクリア
            #txtArg.SetValue("")
            txtArg.setText("")
            # 選択不可とする
            #txtArg.Enable(False)
            txtArg.setEnabled(False)
            # ツールチップをクリア
            #txtArg.SetToolTip(wx.ToolTip(""))
            txtArg.setToolTip("")
            i += 1               
       
        # 戻り値を設定
        if func.retn == None:
            #self.rettxt.SetValue("")
            #self.rettxt.Enable(False)
            #self.rettxt.SetToolTip(wx.ToolTip(""))
            self.rettxt.setText("")
            self.rettxt.setEnabled(False)
            self.rettxt.setToolTip("")
        else:
            #self.rettxt.SetValue(func.retn.label)
            self.rettxt.setText(func.retn.label)
            ##[inamura 120404]-->
            if (self.statNo==1) or (self.statNo==4):
                #self.rettxt.Enable(False)
                self.rettxt.setEnabled(False)
            else:
                #self.rettxt.Enable(True)
                self.rettxt.setEnabled(True)
            ##<--[inamura 120404]
            #tip = wx.ToolTip(func.retn.tip)
            #self.rettxt.SetToolTip(tip)
            if func.retn.tip.strip() == "":
                #tip.Enable(False)
                pass
            else:
                #tip.Enable(True)
                self.rettxt.setToolTip(func.retn.tip)
        
        ##[inamura 120404]-->
        """
        try:
            # Resumtion Booked 中であれば
            if self.statNo == 4:
                # Resumtion Bookable へ戻す
                self.statNo = 2
                self.ChangeBtnStatus()    
                # 予約解除のワーニングを表示
                raise UtilPlot.PlotException('Sequencer', 'S002', ())
        except UtilPlot.PlotException, ex:
            UtilPlot.PlotMessage(self.frame, ex)
        """
        ##<--[inamura 120404]
    ##########################################
    def OnSelectTree(self, evt=None) :
        """
        ツリー選択イベントハンドラ
        @param  evt イベント情報
        @retval 無し
        """ 
        # 選択された文字列を取得
        #text = self.tree.GetItemText(evt.GetItem())
        text = self.tree.currentItem().text(0)
        # 関数一覧から検索
        for func in self.rgfuncs: 
            # 関数名称か
            if func.mfname == text:   
                self.activeFnc = func
                # 関数ドキュメントをテキストボックスへ表示
                #self.fdocTxt.SetValue(func.fdoc)
                self.fdocTxt.setPlainText(func.fdoc)
                # ツールチップを設定
                #tip = wx.ToolTip(func.fdoc)
                #self.fdocTxt.SetToolTip(tip) 
                if func.fdoc.strip() == "":
                    #tip.Enable(False)
                    self.fdocTxt.setToolTip("")
                else:
                    #tip.Enable(True)
                    self.fdocTxt.setToolTip(func.fdoc)
                return
        # 関数ではない
        self.activeFnc = None
        # 関数ドキュメントをクリア
        #self.fdocTxt.SetValue("")
        self.fdocTxt.clear()
         
    
    #########################################
    def OnRemove(self, evt=None):
        """
        Remove ボタン押下イベント処理
        選択関数を実行リストから削除
        @param evt　　イベント
        @retval 無し
        """
        # リストが空でなければ
        """
        if self.list1.GetItemCount() > 0:
            index = self.list1.GetFirstSelected()
            # 選択行があるか
            if index >= 0:
                self.lock.acquire()
                ##[inamura 120424]-->
                index_list = [index]
                while(True):
                    index = self.list1.GetNextSelected(index)
                    if index < 0:
                        break
                    index_list.append( index )
                    self.list1.Select(index, False)
        """
        if self.list1.topLevelItemCount() > 0:
            selected_items = self.list1.selectedItems()

            if len(selected_items)>0:
                self.lock.acquire()
                index_list = []
                for an_item in selected_items:
                    index_list.append( self.list1.indexOfTopLevelItem( an_item ) )
                self.list1.selectionModel().clearSelection()
                
                index_list.sort()
                num_of_removed = 0
                for an_index in index_list:
                    index = an_index - num_of_removed
                    # if under executing
                    try:
                        if self.lineFuncs[index].stat==1:
                            raise UtilQt.PlotException('Sequencer', 'S012', ())
                        elif (self.statNo==2) and (self.lineFuncs[index].stat==2):
                            continue
                        else:
                            self.rd.CheckBackwash(index, self.lineFuncs)
                            # 選択行を削除
                            #self.list1.DeleteItem(index)
                            self.list1.takeTopLevelItem(index)
                            self.lineFuncs[index].ClearResult()
                            del self.lineFuncs[index]
                            # Begin ボタンの選択可/不可を設定
                            self.ChangeStepsStatus()
                            self.OnClearAllArgs()
                            num_of_removed += 1
                            
                    except UtilQt.PlotException, ex:
                        self.lock.release()
                        #UtilPlot.PlotMessage(self.frame, ex)
                        UtilQt.PlotMessage(self, ex)

                self.lock.release()
                """
                # 実行中か
                try:
                    if self.lineFuncs[index].stat == 1:
                        raise UtilPlot.PlotException('Sequencer', 'S012', ())
                    else:
                        # 削除するステップの影響が及ぶステップの結果をクリア
                        self.rd.CheckBackwash(index, self.lineFuncs)
                        # 選択行を削除
                        self.list1.DeleteItem(index)
                        self.lineFuncs[index].ClearResult() ##[inamura 120128]
                        del self.lineFuncs[index]
                        # Begin ボタンの選択可/不可を設定

                        self.ChangeStepsStatus()
                        self.lock.release()
                        self.OnClearAllArgs() ##[inamura 120304]
                        
                except UtilPlot.PlotException, ex:
                    self.lock.release()
                    UtilPlot.PlotMessage(self.frame, ex)
                """
                ##<--[inamura 120424]
        self.list1_selected=self.LIST1_UNSELECTED
        
    #########################################
    def OnBegin(self, evt=None):
        """
        Exec ボタン押下イベント処理
        関数リストを実行
        @param evt　　イベント
        @retval 無し
        """

        # 関数リストの最初から実行実行
        self.DoStart(0)

    #########################################
    def DoStart(self, index):
        """
        実行開始準備処理
        @param index 開始行
        @retval 無し
        """    
        # 状態変更(→　In Process)
        self.statNo = 1
        self.ChangeBtnStatus()
        # 選択状態を消す
        #ai = self.list1.GetFirstSelected()
        #if ai >=0:
        #    self.list1.Select(ai, False)
        self.list1.selectionModel().clearSelection()
        self.list1_selected=self.LIST1_EXECUTED
        self.OnClearAllArgs() ##[inamura 120403]
    
        # 開始行の後の実行結果を削除
        i = index
        while i < len(self.lineFuncs):
            self.lineFuncs[i].ClearResult()
            i += 1    

        # 関数リストの実行を開始
        self.execC.OnStart(index, self.lineFuncs)

        # 実行状態を監視するために、0.5秒毎のタイマーをセット 
        #self.timer = wx.Timer(self.frame)
        #self.timer.Start(500)
        #self.frame.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.OnTimer)
        self.timer.start(500)
         
    #############################################
    def OnTimer(self, evt=None):
        """
        タイマールーチン
        @param  evt イベント情報
        @retval 無し
        """

        self.lock.acquire()
        #lnum = self.list1.GetItemCount()
        lnum = self.list1.topLevelItemCount()
        # 開始時間と終了時間を表示
        for i in range(lnum):
            # 実行開始時間

            #self.list1.SetStringItem(i, 1, self.lineFuncs[i].beginTime )
            self.list1.topLevelItem(i).setText(1, self.lineFuncs[i].beginTime )
            # 実行終了時間
            #self.list1.SetStringItem(i, 2, self.lineFuncs[i].endTime)
            self.list1.topLevelItem(i).setText(2, self.lineFuncs[i].endTime )
            #実行状態イメージ表示
            stNum = self.lineFuncs[i].stat+1
            # 実行可であれば
            if self.lineFuncs[i].stat >= 0:
                #self.list1.SetItemImage(i, stNum)
                self.list1.topLevelItem(i).setIcon(0,self.statusImage[stNum])

        self.lock.release()
        # エラーがあるか
        if self.execC.erstatus > 0:
            # Aborted 表示
            #self.list1.SetStringItem(self.execC.execNum, self.execC.erstatus, "Aborted" )
            self.list1.topLevelItem(self.execC.execNum).setText( self.execC.erstatus, "Aborted" )
            # タイマーを停止
            #self.timer.Stop()
            self.timer.stop()
            # 状態変更(→ Executable)
            self.statNo = 0
            self.ChangeBtnStatus() 
            # 実行時エラーの表示
            #wx.MessageBox(self.execC.ermessage, 'Run-time error')
            ret = QtGui.QMessageBox().critical(None,u"Run-time Error", self.execC.ermessage, QtGui.QMessageBox.Ok )
            return

        # シーケンスが停止したか
        if self.execC.status < 0:
            # タイマーを停止
            #self.timer.Stop()
            self.timer.stop()

            # In Process または Resumption Bookable 中か
            if self.statNo == 1 or self.statNo == 2:
                # 状態変更(→ Executable)
                self.statNo = 0
            # Resumption NOT Bookable 中か
            elif self.statNo == 3:
                # 状態変更(→　Inexecutable)
                self.statNo = -1
            # Resumption Booked 中か

            elif self.statNo == 4:
                # 関数リストの実行
                self.DoStart(self.resumeIndex)
            # 状態変更後の処理
            self.ChangeBtnStatus()
            self.OnClearAllArgs()

    #########################################
    def OnStop(self, evt=None):
        """
        Abort ボタン押下イベント処理
        関数リストの実行停止
        @param evt　　イベント
        @retval 無し
        """ 
        ##[inamura 120404]-->
        # if "Waiting to Resume", not send Stop to commands
        if self.statNo == 4:
            self.statNo = 2
        else:
            # シーケンスの実行停止要求をだす
            self.execC.OnStop()
        ##<--[inamura 120404]

        # 状態変更(→　Resumption Bookable)
        self.statNo = 2
        self.ChangeBtnStatus()
        
    #########################################
    def ChangeBtnStatus(self):
        """
        状態変更対応処理
        状態表示を変更
        ボタン類の選択可/不可を設定
        @param 無し
        @retval 無し
        """
        # 状態文字列を取得し表示
        strStat = self.STATUS[self.statNo]
        #self.statTxt.SetLabel(strStat)
        self.statTxt.setText(strStat)

        # 実行中か
        if self.statNo == 1: 
            # スクリプト編集関連ボタンは選択不可
            for bt in self.bttns:
                #bt.Enable(False)
                bt.setEnabled(False)
            # Stop 以外のボタンは選択不可
            #self.btBegin.Enable(False)
            #self.btResume.Enable(False)
            #self.btStop.Enable(True)
            self.btBegin.setEnabled(False)
            self.btResume.setEnabled(False)
            self.btStop.setEnabled(True)
        # 実行中以外
        else:
            ##[inamura 120404]-->
            if self.statNo==4:
                for bt in self.bttns:
                    #bt.Enable(False)
                    bt.setEnabled(False)
                #self.btStop.Enable(True)
                #self.btResume.Enable(False)
                self.btStop.setEnabled(True)
                self.btResume.setEnabled(False)
                return
            ##<--[inamura 120404]
            # スクリプト編集関連ボタンは選択可
            for bt in self.bttns:
                #bt.Enable(True)
                bt.setEnabled(True)
            
            #self.btStop.Enable(False)
            self.btStop.setEnabled(False)

            # Executable なら
            if self.statNo == 0: 
                #self.btBegin.Enable(True)
                #self.btSaveas.Enable(True)
                #self.btResume.Enable(False)
                self.btBegin.setEnabled(True)
                self.btSaveas.setEnabled(True)
                self.btResume.setEnabled(False)
                # 正常終了データがあれば、Resume も選択可とする
                for func in self.lineFuncs:
                    # 正常終了データがあるか
                    if func.stat == 2:
                        #self.btResume.Enable(True)
                        self.btResume.setEnabled(True)
                        break 
            # Inexecutable 、 Not Acceptable または Waiting to Resume なら
            elif self.statNo == -1 or self.statNo >= 3:
                #self.btBegin.Enable(False)
                #self.btResume.Enable(False)
                #self.btSaveas.Enable(False)
                self.btBegin.setEnabled(False)
                self.btResume.setEnabled(False)
                self.btSaveas.setEnabled(False)
            # Waiting to Stop なら    
            elif self.statNo == 2:
                #self.btBegin.Enable(False)
                #self.btResume.Enable(True)
                self.btBegin.setEnabled(False)
                self.btResume.setEnabled(True)
            
            # 再開処理時は、Open、Save、 Clear　は選択不可とする
            if self.statNo >= 2:
                #self.btOpen.Enable(False)
                #self.btSaveas.Enable(False)
                #self.btClear.Enable(False)
                self.btOpen.setEnabled(False)
                self.btSaveas.setEnabled(False)
                self.btClear.setEnabled(False)

         
            # ステップ数が0か
            #if self.list1.GetItemCount()== 0:
            if self.list1.topLevelItemCount()== 0:
                for bt in self.bttns:
                    #bt.Enable(False)
                    bt.setEnabled(False)
                #self.btOpen.Enable(True)
                #self.btAdd.Enable(True)
                self.btOpen.setEnabled(True)
                self.btAdd.setEnabled(True)
                # タイトルのファイル名をクリア
                #self.frame.SetTitle(self.frameTitle+ " - New")
                self.setWindowTitle(self.frameTitle+ " - New")
                # リストのツールチップをクリア
                #self.list1.SetToolTip(wx.ToolTip("New"))
                self.list1.setToolTip("New")
                self.docTip = ""    
                
            else: # ステップ数が0でないとき
                self.OnSelect()           
        
    #########################################
    def OnResume(self, evt=None):
        """
        Resume ボタン押下イベント処理
        関数リストの実行を再開
        @param evt　　イベント
        @retval 無し
        """ 
        # 選択中の行を取得
        #index = self.list1.GetFirstSelected()        
        selected = self.list1.currentItem()
        index = -1
        if isinstance(selected,QtGui.QTreeWidgetItem):
            index = self.list1.indexOfTopLevelItem( selected )
        try:
            # 選択行が無ければ
            if index < 0:
                ##[inamura 120404]-->
                #raise UtilPlot.PlotException('Sequencer', 'S003', ())
                
                for i in range(len(self.lineFuncs)):
                    if self.lineFuncs[i].stat ==0:
                        index = i
                        break;
                    # command under executing?
                    if self.lineFuncs[i].stat ==1:
                        index=i+1
                        break
                ##<--[inamura 120404]
            ##[inamura 120522]-->
            ## if selected command is under executing, resume from next command
            elif self.lineFuncs[index].stat == 1:
                index+=1
            else:
                i = 0
                # 再開行の上に、正常終了以外の行がないかをチェック
                while i < index:
                    if self.lineFuncs[i].stat != 2:
                        # 実行中の行か
                        if self.lineFuncs[i].stat != 1:
                            raise UtilQt.PlotException('Sequencer', 'S013', ())
                    i += 1
            ##<--[inamura 120522]
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return
 
        # Executable 中か
        if self.statNo == 0:
            # 関数リストの実行
            self.DoStart(index)
        # Resumption Bookable: 再開予約可中
        if self.statNo == 2:
            # 状態変更(→　Resumption Booked )
            self.statNo = 4
            self.resumeIndex = index
            # 状態表示変更
            strStat = self.STATUS[self.statNo]
            #self.statTxt.SetLabel(strStat)
            self.statTxt.setText(strStat)
            self.ChangeBtnStatus() ##[inamura 120404]
            self.OnClearAllArgs() ##[inamura 120404]
        
    #########################################
    def OnVisualize(self, evt=None):
        """
        Visualize ボタン押下イベント処理
        Visualize 実行画面を開く
        @param evt　　イベント
        @retval 無し
        """ 
        # 先に起動されているか
        if self.vis == None:
            # 画面を作成
            #self.vis = ExecVisualize(self.frame, self.lineFuncs, self.lock)
            self.vis = ExecVisualize(self)  # 2010.01.05 Minakawa
        else:
            # 画面を表示
            self.vis.OnClose(None) ##[inamura 120424]
            self.vis.ShowFrame()


    #########################################
    def OnClear(self):
        """
        Clear ボタン押下イベント処理
        関数リストをクリア
        @param evt　　イベント
        @retval 無し
        """ 
        # リストをクリア
        #self.list1.DeleteAllItems()
        self.list1.clear()
        ##[inamura 120128]-->
        for i in range(len(self.lineFuncs)):
            self.lineFuncs[i].ClearResult()
        ##<--[inamura 120128]
        self.lineFuncs = []   
        # 状態変更
        self.statNo = -1
        self.ChangeBtnStatus()

    #########################################
    def OnOpen(self):
        """
        File Open ボタン押下イベント処理
        シーケンスファイルを開く
        @param evt　　イベント
        @retval 無し
        """
        # ファイルオープンダイアログを開き、シーケンスを読み込む
        try:
            ftpl = self.sfile.OpenSequence(self.rgfuncs, self.acqF, defPath=os.getcwd()) #[inamura 161216]
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return 
        else:
        # ファイルオープンダイアログでファイルを指定しないとき(Noneが戻り値のとき)
            if ftpl is None:
                return
        
        try:
            fname, funcs = ftpl
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return 
        
        ## [inamura 100519]-->
        # リストをクリアしない
        #self.list1.DeleteAllItems()
        #self.lineFuncs = funcs
        self.lock.acquire()
        ## <--[inamura 100519]
        
        # 1行づつ読み込む
        for func in funcs:
            ## [inamura 100519]-->
            self.lineFuncs.append(func)
            ## <--[inamura 100519]
            #　リストに1行を追加
            self.SetTxt(func)

        # 1行目を選択状態へ
        ## [inamura 100519]-->
        #self.list1.Select(len(funcs)-1, False)
        #self.list1.Select(0, True)
        #self.list1.Select( len(self.lineFuncs)-1, False )
        #self.list1.Select( len(self.lineFuncs)-len(funcs), True )
        self.list1.setItemSelected( self.list1.topLevelItem( len(self.lineFuncs)-1 ), False )
        self.list1.setItemSelected( self.list1.topLevelItem( len(self.lineFuncs)-len(funcs) ), True )
        ## <--[inamura 100519]
                        
        # 選択行の内容を、テキストボックスへ反映
        self.OnSelect()
                                        
        # タイトルバーとリストのツールチップを更新
        self.UpdateSequence(fname) 
                             
        # Begin ボタンの選択可/不可を設定

        self.ChangeStepsStatus()
        ## [inamura 100519]-->
        self.lock.release()
        ## <--[inamura 100519]
                
    #########################################
    def OnSaveas(self):
        """
        Save As ボタン押下イベント処理
        関数実行リストを保存
        @param evt　　イベント
        @retval 無し
        """ 
        # ファイル保存ダイアログを開き、シーケンスを保存
        try:
            fname = self.sfile.SaveSequence(self.lineFuncs, self.acqF) 
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return
        # キャンセルされていなければ
        if fname != None:
            # タイトルバーとリストのツールチップを更新
            self.UpdateSequence(fname) 

    ##[inamura 160822]-->
    #########################################
    def OnChangeCurrentDir(self):
        """
        Current Dir ボタン押下イベント処理
        関数実行リストを保存
        @param evt　　イベント
        @retval 無し
        """
        dirname = QtGui.QFileDialog.getExistingDirectory(self, caption="Choose Current Directory", dir=os.getcwd() )
        if dirname!="":
            os.chdir( dirname )
            self.currentDirTxt.setText( os.getcwd() )
        """
        dlg = wx.DirDialog( self.frame, message="Choose Current Directory", defaultPath=os.getcwd() )
        if dlg.ShowModal()==wx.ID_OK:
            os.chdir( dlg.GetPath() )
            self.currentDirTxt.SetLabel( os.getcwd() )
        dlg.Destroy()
        """
    ##<--[inamura 160822]
    #########################################
    def UpdateSequence(self, fname):
        """
        タイトルバーのシーケンス名とツールチップを更新
        @param  fname　　シーケンスファイル名
        @retval 無し
        """ 
        # タイトルに、ファイル名を付加
        title = u"%s - %s" % (self.frameTitle, fname)
        #self.frame.SetTitle(title)
        self.setWindowTitle(title)
        # ツールチップ文字列を作成
        tip = u"\n  File Name: " + fname + "  \n" 
        # 最終更新日時を取得

        # 関数ドキュメントを取得 
        ftime = self.sfile.GetFileTime()
        tip = tip + u"  Created or Updated at " + ftime + "  \n\n" 
        
        fDoc = self.sfile.GetFileDoc()
        if fDoc:
            tip = tip + fDoc
        # リストにツールチップを表示
        #self.list1.SetToolTip(wx.ToolTip(tip))
        self.list1.setToolTip(tip)

    #########################################
    def OnSet(self):
        """
        Set ボタン押下イベント処理
        設定された引数と戻り値の変数名を変更
        @param evt　　イベント
        @retval 無し
        """ 
        # 選択状態の行が無ければ
        #index = self.list1.GetFirstSelected()
        selected = self.list1.selectedItems()
        index = -1
        if len(selected)==1:
            index = self.list1.indexOfTopLevelItem( selected[0] )
        try:
            if index < 0:
                raise UtilQt.PlotException('Sequencer', 'S003', ())
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return 

        self.lock.acquire()
        # 当該行の関数データを取得

        func = self.lineFuncs[index]

        i = 0
        strArg = ""
        for arg in func.args:
            # 文字列とテキストボックスのコントロールを取得 
            stt, txtArg = self.argList[i]
                
            if arg.label == "HISTORY":
                item = "HISTORY"
            else:
                # 値を取得
                #item = txtArg.GetValue().strip()
                item = txtArg.text().strip()
                i += 1
            # 入力の型チェック
            if not self.rd.CheckArgType(arg, item):
                self.lock.release()
                return      
            
            # デフォルト値の型が実数のときテキストボックスに実数を表示
            if arg.type == "float":
                item = "%s" %float(item)
                #txtArg.SetValue(item)
                txtArg.setText(item)

        # 戻り値があるか
        if func.retn != None:
            # 戻り値のラベルを取得して置き換え
            #strRet = self.rettxt.GetValue().strip()
            strRet = self.rettxt.text().strip()
            try:
                if strRet=="":
                    raise UtilQt.PlotException('Common', 'C013', ("Return Label",))
            except UtilQt.PlotException, ex:
                #UtilPlot.PlotMessage(self.frame, ex)
                UtilQt.PlotMessage(self, ex)
                return
            # 戻り値がある場合、変更したステップの影響が及ぶステップの結果をクリア
            self.rd.CheckBackwash(index, self.lineFuncs)
            # 戻り値ラベルの入れ替え(影響を評価した後に入れ替えること) 
            func.retn.label = strRet 
        line = self.rd.MakeLine(func)

        # リストを書き換える
        #index = self.list1.GetFirstSelected() 
        #self.list1.SetStringItem(index, 0, line)
        self.list1.currentItem().setText(0,line)

        # 変更した関数の結果をクリア
        func.ClearResult()
        self.lock.release()
        # Start ボタンの選択可/不可を設定
        self.list1_selected = self.LIST1_UNSELECTED
        self.ChangeStepsStatus()


    #########################################
    #def OnClose(self):
    def eventClose(self,evt):
        """
        クローズイベント処理
        関数リストが実行中かどうかをチェック
        @param  evt　　イベント
        @retval 無し
        """ 
        
        try:
            # Executable 中または　Inexecutable 中以外はクローズできない
            if self.statNo > 0:
                evt.ignore()
                raise UtilQt.PlotException('Sequencer', 'S004', ())
            
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            evt.ignore()
            UtilQt.PlotMessage(self, ex)
            return 

        if self.vis != None:
            self.vis.close()
        #self.frame.Destroy()
        evt.accept()
        #self.close()
        
    ###################################
    def OnUp(self):
        """
        表示順変更ボタン「↑」押下イベント処理
        @param evt イベント
        @retval 無
        """
        #index = self.list1.GetFirstSelected()
        index=-1
        selected = self.list1.currentItem()
        if isinstance(selected,QtGui.QTreeWidgetItem):
            index = self.list1.indexOfTopLevelItem( selected )
        if index < 0:
            return
        self.lock.acquire()

        #self.list1.Select(index,False)
        self.list1.setItemSelected( selected, False )
        # 選択した行とその上の行を入れ替え
        dat = self.lineFuncs[index]     
        self.lineFuncs[index] = self.lineFuncs[index-1]
        self.lineFuncs[index-1] = dat
        # 入れ替えて行を表示
        for i in range(index-1,index+1): 
            sLine = self.rd.MakeLine(self.lineFuncs[i])
            #self.list1.SetStringItem(i,0,sLine)
            self.list1.topLevelItem(i).setText(0, sLine)
        
        # 入れ替え後、行を選択
        #self.list1.Select(index-1,True)
        self.list1.setCurrentItem( self.list1.topLevelItem(index-1) )
        self.list1_selected = self.LIST1_UNSELECTED
        self.lock.release()
        # 選択行から下の行は「未実行」
        for i in range(index-1,len(self.lineFuncs)):
            # 開始・終了時間表示をクリア
            self.lineFuncs[i].stat = 0   
            #self.list1.SetStringItem(i,1,"")  
            #self.list1.SetStringItem(i,2,"")  
            #self.list1.SetItemImage(i,1)
            self.list1.topLevelItem(i).setText(1, "")
            self.list1.topLevelItem(i).setText(2, "")
            self.list1.topLevelItem(i).setIcon(0,self.statusImage[1])
            
        self.ChangeStepsStatus()                    

    ####################################
    def OnDown(self):
        """
        表示順変更ボタン「↓」押下イベント処理
        @param evt: イベント
        @retval 無
        """
        
        #index = self.list1.GetFirstSelected()
        index=-1
        selected = self.list1.currentItem()
        if isinstance(selected,QtGui.QTreeWidgetItem):
            index = self.list1.indexOfTopLevelItem( selected )
        if index < 0:
            return
        self.lock.acquire()
        #self.list1.Select(index,False)
        self.list1.setItemSelected( selected, False )
    
         # 選択した行とその下の行を入れ替え
        dat = self.lineFuncs[index]       
        self.lineFuncs[index] = self.lineFuncs[index+1]
        self.lineFuncs[index+1] = dat
         # 入れ替えた行を表示
        for i in range(index,index+2):    
            sLine = self.rd.MakeLine(self.lineFuncs[i])
            #self.list1.SetStringItem(i,0,sLine)
            self.list1.topLevelItem(i).setText(0, sLine)
        # 入れ替えた行を選択    
        #self.list1.Select(index+1,True)
        self.list1.setCurrentItem( self.list1.topLevelItem(index+1) )
        self.list1_selected = self.LIST1_UNSELECTED
        self.lock.release()
        # 入れ替えて選択行より下の行は「未実行」
        for i in range(index,len(self.lineFuncs)):
             # 開始時間・終了時間をクリア
            #self.list1.SetItemImage(i,1)
            #self.list1.SetStringItem(i,1,"") 
            #self.list1.SetStringItem(i,2,"")
            self.list1.topLevelItem(i).setText(1, "")
            self.list1.topLevelItem(i).setText(2, "")
            self.list1.topLevelItem(i).setIcon(0,self.statusImage[1])
            
        self.ChangeStepsStatus()

    ####################################
    def OnCopyAdd(self):
        """
        表示順変更ボタン「↓」押下イベント処理
        @param evt: イベント
        @retval 無
        """

        """
        index = self.list1.GetFirstSelected()
        if index < 0:
            return
        index_list = [index]
        while(True):
            index = self.list1.GetNextSelected(index)
            if index < 0:
                break
            index_list.append( index )
        """
        selected_items = self.list1.selectedItems()
        if len(selected_items)==0:
            return
        index_list = []
        for an_item in selected_items:
            index_list.append( self.list1.indexOfTopLevelItem( an_item ) )
            self.list1.setItemSelected( an_item, False )
        index_list.sort()
        
        self.lock.acquire()
        #for index in index_list:
        #    self.list1.Select(index,False)

        for index in index_list:
            # Add Selected command at last of lineFuncs
            func = self.lineFuncs[index].Copy()
            self.lineFuncs.append( func )
            # リストに1行追加、テキストボックスに値を設定
            self.SetTxt(func)
        
        # Begin ボタンの選択可/不可を設定
        self.list1_selected=self.LIST1_UNSELECTED
        self.ChangeStepsStatus()
        self.lock.release()        

    ##[inamura 120321]-->
    ####################################
    def LoadInitSequence(self):
        """
         イニシャルシークエンス読み込み
         起動時にシークエンスを読み込む
         @param None
         @retval None
        """
        path = os.path.join( os.environ["UTSUSEMI_USR_PRIV_HOME"],"ana",INITSEQFILE )
        if not os.path.exists(path):
            print "There is no initial sequence file.",path
            return
        
        try:
            ftpl = self.sfile.OpenSequence(self.rgfuncs, self.acqF, False, path )
        except:
            print "Initial file format is invalid."
            return
        
        try:
            fname, funcs = ftpl
        except UtilQt.PlotException, ex:
            #UtilPlot.PlotMessage(self.frame, ex)
            UtilQt.PlotMessage(self, ex)
            return 
            
        self.lock.acquire()
        
        # 1行づつ読み込む
        for func in funcs:
            self.lineFuncs.append(func)
            #　リストに1行を追加
            self.SetTxt(func)

        # 1行目を選択状態へ
        #self.list1.Select( len(self.lineFuncs)-1, False )
        #self.list1.Select( len(self.lineFuncs)-len(funcs), True )
        self.list1.setItemSelected( self.list1.topLevelItem( len(self.lineFuncs)-1 ), False )
        self.list1.setItemSelected( self.list1.topLevelItem( len(self.lineFuncs)-len(funcs) ), True )
                        
        # 選択行の内容を、テキストボックスへ反映
        self.OnSelect()
                                        
        # タイトルバーとリストのツールチップを更新
        self.UpdateSequence(fname) 
                             
        # Begin ボタンの選択可/不可を設定
        self.ChangeStepsStatus()
        self.lock.release()

        ##<--[inamura 120321]

    ##[inamura 120424]-->
    ####################################
    def OnDeselectedList(self):
        """
        Listの選択が外れた時の処理
        @param evt  
        @retval None
        """
        self.OnClearAllArgs()
        #self.btRemove.Enable(False)
        #self.btCopyAdd.Enable(False)
        #self.btUp.Enable(False)
        #self.btDown.Enable(False)
        self.btRemove.setEnabled(False)
        self.btCopyAdd.setEnabled(False)
        self.btUp.setEnabled(False)
        self.btDown.setEnabled(False)
    ##<--[inamura 120424]

    ##[inamura 120403]-->
    ####################################
    def OnClearAllArgs(self):
        """
         引数欄をクリアする
         @param None
         @retval None
        """
        # テキストボックスをデフォルトに
        for strArg,txtArg in self.argList:
            # ラベルをデフォルトに戻す
            #strArg.SetLabel("Argument:")
            strArg.setText("Argument:")
            # 値をクリア
            #txtArg.SetValue("")
            txtArg.setText("")
            # 選択不可とする
            #txtArg.Enable(False)
            txtArg.setEnabled(False)
            # ツールチップをクリア
            #txtArg.SetToolTip(wx.ToolTip(""))
            txtArg.setToolTip("")
        # 戻り値をクリア
        #self.rettxt.SetValue("")
        #self.rettxt.Enable(False)
        #self.rettxt.SetToolTip(wx.ToolTip(""))
        self.rettxt.setText("")
        self.rettxt.setEnabled(False)
        self.rettxt.setToolTip("")

    ##<--[inamura 120403]

##[inamura 110105]-->
#######################################
#  Splash 
#######################################
"""
class UtsusemiSplashScreen(wx.SplashScreen):
    def __init__(self,splash_path):

        bmp = wx.Image(splash_path).ConvertToBitmap()
        wx.SplashScreen.__init__(self,bmp,
                                 wx.SPLASH_CENTRE_ON_SCREEN|wx.SPLASH_TIMEOUT,
                                 5000, None, -1)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.fc = wx.FutureCall( 2000, self.ShowMain)

    def OnClose(self, evt):
        evt.Skip()
        self.Hide()
        if self.fc.IsRunning():
            self.fc.Stop()
            self.ShowMain()

    def ShowMain(self):
        pass
"""
##<--[inamura 110105]
        
#######################################
#  Sequencer
#######################################  
class Sequencer(object):
    """
    Application Class 
    """
    #########################################
    def __init__(self, modules=None):
        """
        アプリケーションスタート
        @param  modules  ファサードモジュールのリスト
                指定が無い場合は、デフォルトのモジュール
        @retval 無
        """
        # 測定シーケンスか 
        if modules!=None and modules[0] =='0':
            pass
        else:
            try:
                Code = os.environ["UTSUSEMI_SYS_NAME"]
            except:
                print "Error!: No environment settings."
                return
            # 指定無しか
            if modules == None:
                try:
                    ##[inamura 140818]-->
                    #import Sequencer_facades
                    #COMMON = (Code, Sequencer_facades.__AnaFacades__)
                    #VISUALIZER = ("Visualizer",Sequencer_facades.__VisFacades__)
                    import glob
                    ana_facades=[]
                    vis_facades=[]
                    for pypath in sys.path:
                        fpath=glob.glob( os.path.join( pypath, BASEFACADEFILE ) )
                        for a_fpath in fpath:
                            path_to_dir, module_file = os.path.split( a_fpath )
                            isBaseCommand = False
                            if path_to_dir.find(Code)>=0:
                                isBaseCommand = True
                            
                            module_name = module_file[:-3]
                            mod_tmp = __import__(module_name)
                            for ana_mod in mod_tmp.__AnaFacades__:
                                if not ana_mod in ana_facades:
                                    if isBaseCommand:
                                        ana_facades.insert( 0, ana_mod )
                                    else:
                                        ana_facades.append( ana_mod )
                            for vis_mod in mod_tmp.__VisFacades__:
                                if not vis_mod in vis_facades:
                                    if isBaseCommand:
                                        vis_facades.insert( 0, vis_mod )
                                    else:
                                        vis_facades.append( vis_mod )
                    COMMON = (Code, ana_facades)
                    VISUALIZER = ("Visualizer", vis_facades)
                    ##<--[inamura 140818]
                    
                except:
                    # デフォルトモジュール
                    COMMON = (Code, ["Cmm","Com"])
                    VISUALIZER = ("Visualizer", ["D1Plotter"])
            else:
                #mod_list_st = modules.split(" ")
                mod_list_st = modules
                enable_mod_list = []
                for mod_st in mod_list_st:
                    try:
                        tmp = __import__(mod_st)
                        enable_mod_list.append(mod_st)
                    except:
                        print( "########## Error on Sequence Editor" )
                        print( "########## Could not import module =",mod_st )
                        continue
                COMMON = (Code, enable_mod_list )
                VISUALIZER = ("Visualizer", ["D1Plotter"])
            
            modules = [COMMON, VISUALIZER]

        #app = wx.App()
        app = QtGui.QApplication(sys.argv)
        
        #splash_path = os.path.join( os.environ["UTSUSEMI_BASE_DIR"],"ana","Reduction","LOGO_utsusemi_s.png" )
        splash_path = os.path.join( os.environ["UTSUSEMI_BASE_DIR"],"ana","Reduction","LOGO_utsusemi_3_c_short.png" )
        self.splash = None
        if os.path.exists(splash_path):
            #self.splash = UtsusemiSplashScreen(splash_path)
            #self.splash.Show()
            pixmap = QtGui.QPixmap( splash_path )
            self.splash = QtGui.QSplashScreen(pixmap,QtCore.Qt.WindowStaysOnTopHint)
            self.splash.setMask(pixmap.mask())
            self.splash.show()
            self.splash.showMessage(u"Now Launching ...")
            app.processEvents()
            import time
            time.sleep(2)
        
        seq=SequenceEditor(modules)
        if self.splash!=None:
            self.splash.finish(seq)
        sys.exit(app.exec_())
        #app.MainLoop() 


        
if __name__ == '__main__':

    # 引数が指定されていれば置き換え
    if len(sys.argv) > 1:
        mdls = sys.argv[1:]
        Sequencer(mdls)
    else:
        Sequencer()
