#!/usr/bin/python
# coding=utf-8

from os import getenv
from PyQt4.QtCore import SIGNAL, Qt, SLOT, pyqtSlot, pyqtSignal, QString
from PyQt4.QtGui import QGridLayout, QLayout, QApplication, QLabel, QToolTip, QCursor
import sys
from common import common_run
from winDesktopUnit import WinDesktopUnit

from setting import SettingDlg
from ui_qss.winVirturlListQss import WinVirturlListQss
from threading import Thread
from time import sleep
from messageDialog import MessageDialog
from logger.logrecord import LogRecord

###################################
#  Virturl
###################################
from VirtApp.AppPannelWidget import AppPannelWidget  # app Windown
from VirtApp.AppUser import AppUser  # app class
from VirtApp.AppObject import AppObject
from winDebug import WinDebug  # 调试设置窗口
from logout import Logout

from changePassword import ChangePassword
from usbip.usbip import UsbIp_Mgr
from usbip.usbipManage import UsbIpManage
from usbip.usbipManage2 import UsbIp_Mgr as UsbIpManage2
from usbip.detectUSB import DetectUSB

from WaitingDialog import WaitingDialog
from common.info_dialog import InfoDialog
from sendCmd.validate.userValidate import UserValidate
from common import common_run
import os
from syncClock.syncClockThread import SyncClockThread  # 时钟同步

try:
    _encoding = QApplication.UnicodeUTF8


    def _translate(context, text, disambig):
        return QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QApplication.translate(context, text, disambig)


class Tmp_label(QLabel):
    def __init__(self, parent=None):
        super(Tmp_label, self).__init__(parent)
        self.update_style_sheet()

    def update_style_sheet(self):
        __font_size = str(common_run.get_height(10.0))
        self.setStyleSheet("font: 63 " + __font_size + "pt;color:rgb(255,255,255)")

    def enterEvent(self, ee):
        return QToolTip.showText(QCursor().pos(), common_run.tip_label_name)


class WinVirturlList(WinVirturlListQss):
    userloged = False
    ''' 虚拟机列表 虚拟应用列表'''
    # ------------------------ 初始化 -------------------------------
    def __init__(self, userInfo=None, CenterIP=None, vmInfoList=None, agentInfo=None, appInfoList=None):
        super(WinVirturlList, self).__init__()
        self.label_user_name_sign.setHidden(True)
        self._tmp_label = Tmp_label(self)
        self.verticalLayout_4.addWidget(self._tmp_label)
        # changed by pbc for userlabel value -top
        try:
            display_name = "user"
            tmp_userInfo = common_run.user_information
            if tmp_userInfo.has_key("result"):
                if tmp_userInfo['result'].has_key("result"):
                    if tmp_userInfo['result']['result'].has_key('displayName'):
                        display_name = tmp_userInfo['result']['result']['displayName']
            self.label_user_name_sign.setText(QString(display_name))
            common_run.tip_label_name = QString(display_name)
            self._tmp_label.setText(QString(display_name))
        except Exception as e:
            LogRecord.instance().logger.exception("parse user info exception!")
        self._tmp_globel_sign = True
        # changed by pbc for userlabel value -end

        #add by pbc for usb used status -top
        ret = common_run.get_usb_set_statu()
        if ret == "00":
            common_run.usb_status = "virt_ip"
        elif ret == "11":
            common_run.usb_status = "network_ip"
        elif ret == "22" or ret == "":
            tmp_userInfo = common_run.user_information
            if tmp_userInfo.has_key("result"):
                if tmp_userInfo['result'].has_key("result"):
                    if tmp_userInfo['result']['result'].has_key('usbType'):
                        usb_statu = tmp_userInfo['result']['result']['usbType']
                        if usb_statu == "0":
                            common_run.usb_status = "virt_ip"
                        elif usb_statu == "1":
                            common_run.usb_status = "network_ip"

        print common_run.usb_status,common_run.user_information,"fukkkkkd"

        #add by pbc for usb used status -end


        self.__userInfo = userInfo
        self.__centerIp = CenterIP
        self.__vmInfoList = None
        self.__userLogout = Logout()
        self.__thread_run = True
        self.__listen_vm_run = True
        self.waitingdlg = WaitingDialog()

        self.__appMsg_Shield = False  # 应用消息屏蔽位
        self.__setting_band_signalslot()  # 绑定信号和槽

        try:
            LogRecord.instance().logger.info("启动 usbip server")
            os.system("pkill usbip-server")

            UsbIpManage2.usbIpServer_run("/mcos/dvclient/log/usbip.log")
            UsbIpManage2.usbIpLogProcess_run("/mcos/dvclient/log/usbip.log")


        except Exception as e:
            info = "useip server : " + e.message
            LogRecord.instance().logger.error(info)

        self.hideRDPSignal = pyqtSignal()  # 隐藏RDP窗口
        self.showRDPSignal = pyqtSignal()  # 显示RDP窗口

        WinVirturlList.userloged = True
        # self.winApp.hide()
        # self.winDesktop.hide()

        self.logout_thread = None

        LogRecord.instance().logger.info("线程同步")
        __syncClick = SyncClockThread(self.__centerIp)
        __syncClick.run()  # 启动时间同步线程

        LogRecord.instance().logger.info("vm desktop  init")
        LogRecord.instance().logger.debug(str(vmInfoList))
        self.desktopVirtListInit(userInfo, vmInfoList)  # 桌面初始化
        LogRecord.instance().logger.info("app desktop  init")
        self.appVirtListInit(userInfo, agentInfo, appInfoList)  # 应用初始化

        if len(vmInfoList) == 0:
            self.__layout_band_winApp()
        if len(appInfoList) == 0:
            self.__layout_band_winDesktop()

        self.__changePasswd = ChangePassword(self.__userInfo, self.__centerIp)  # 实例化 更改密码对象窗口

        self.connect(self, SIGNAL('showReconnectDlgSignal'), self.showReconnectDlg)
        self.connect(self, SIGNAL('hideReconnectDlgSignal'), self.hideReconnectDlg)

        # add  by pbc for split column -top
        self._column = 4
        self.connect(self, SIGNAL('for_screen_changed'), self.resetlayoutforvm)
        # add  by pbc for split column -end

        #######################################################################
        # 启动USB设备监听
        self.__detectUsb = DetectUSB()
        self.__detectUsb.start()
        self.connect(self.__detectUsb, SIGNAL('USBPulginSignal'), self, SIGNAL('USBPlugin'))
        ########################################################################

    def __del__(self):
        super(WinVirturlList, self).__del__()
        WinVirturlList.userloged = False

    # ===================== 初始化应用列表 ===========================
    #                 应用列表初始化 函数
    # ---------------------------------------------------------------
    def appVirtListInit(self, userInfo, agentInfo=None, appInfoList=None):
        if len(appInfoList) == 0:
            self.winApp.hide()
            self.__layout_band_winDesktop()
            return

        try:
            print "-------------- appVirtListInit ---------------"
            print agentInfo
            # #  实例化 AppUser
            appUsr = AppUser(agentInfo["agentDomain"])
            # AppUser.set...
            from des import Des
            appUsr.setPassword(Des.Decrypt(userInfo["userPassword"]))
            # appUsr.setSessionState("")
            appUsr.setAgentIP(agentInfo["agentIp"])
            appUsr.setAgentPort(agentInfo["agentPort"])

            # # 实例化 AppObject 一个应用一个
            for i in range(len(appInfoList)):
                appobj = AppObject(appInfoList[i]["appName"], appInfoList[i]["appId"])
                appobj.setAppCommand(appInfoList[i]["executablePath"])
                appobj.setAppIcon(appInfoList[i]["appId"] + ".png")
                appUsr.updateAppDictionary(appobj)

            self.pannel = AppPannelWidget(self, appUsr)
            self.stackedWidget.addWidget(self.pannel)
            self.connect(self.pannel, SIGNAL("appbackInfo"), self.__appbackInfo)
            self.connect(self, SIGNAL('showRDPSignal'), self.pannel, SIGNAL('showRDPSignal'))
            self.connect(self, SIGNAL('hideRDPSignal'), self.pannel, SIGNAL('hideRDPSignal'))

            # self.pannel = AppPannelWidget(self)
            # self.stackedWidget.addWidget(self.pannel)

        except Exception as e:
            print "[ app Exception ] : ", e.message

    def showReconnectDlg(self):
        InfoDialog.instance().Information(u'提示信息', u'网络异常，正在尝试连接...')

    def hideReconnectDlg(self):
        InfoDialog.instance().hide()

    # ====================== 桌面列表初始化 =============================
    #   描述 ：  vm桌面列表初始化
    #   函能 :  初始化桌面列表
    #   参数 :  vmInfoList : 列表[ vmInfo1{}，vmInfo2{}， ... ，vmInfoN{} ]
    #
    #   返回 ： None
    # ----------------------------------------------------------------------
    def desktopVirtListInit(self, userInfo, vmInfoList):
        LogRecord.instance().logger.debug("userInfo::" + str(userInfo) + ",vmInfoList::" + str(vmInfoList))
        self.__vmInfoList = vmInfoList
        self.__desktopVirtListRemoveAll()  # 进入 先清空 虚拟机桌面列表
        LogRecord.instance().logger.debug("__desktopVirtListRemoveAll")

        if len(vmInfoList) == 0:  # 桌面列表为空
            self.winDesktop.hide()  # 隐藏桌面列表
            self.__layout_band_winApp()
        else:
            self.__layout_band_winDesktop()
        LogRecord.instance().logger.debug("self.__layout_band_winDesktop()")

        from sendCmd.validate.userValidate import UserValidate
        from sendCmd.validate.vmlist import VmList

        LogRecord.instance().logger.debug('__userInfo::' + str(self.__userInfo) + ',__centerIp::' + self.__centerIp)
        uservalidate = UserValidate(self.__userInfo, self.__centerIp)
        LogRecord.instance().logger.debug('uservalidate::' + str(uservalidate))
        vmlist = VmList(self.__userInfo, self.__centerIp)
        LogRecord.instance().logger.debug('vmlist::' + str(vmlist))

        # ========== 线程体函数 =========
        #        更新状态
        # ----------------------------
        def vminfoUpdate():
            LogRecord.instance().logger.debug("enter vminfoUpdate")
            while self.__thread_run:
                try:
                    res = vmlist.getVMlist()
                    LogRecord.instance().logger.debug('res::' + str(res))
                    if res[0] == True:
                        _vminflist = res[1]
                        self.emit(SIGNAL("vminfoUpdate"), _vminflist)
                    else:
                        LogRecord.instance().logger.info(res[1])

                    for i in range(25):
                        if self.__thread_run != True:
                            LogRecord.instance().logger.info("self.__thread_run != True")
                            break
                        sleep(0.2)
                    LogRecord.instance().logger.debug('before terminalRegist')
                    uservalidate.terminalRegist()  # 终端注册
                    LogRecord.instance().logger.debug('after terminalRegist')
                    res2 = uservalidate.sessionIsLogout()  # 检查是否被注销
                    LogRecord.instance().logger.debug('whether user is logged out ::' + str(res2))
                    if res2[0] == True:
                        if UserValidate.logouting:
                            LogRecord.instance().logger.info('UserValidate.logouting')
                            self.emit(SIGNAL("exitVm"), "", "exitAllVm")  # 关闭 window 窗口
                            # if reconnectTimes > 0:
                            #     self.emit(SIGNAL('hideReconnectDlgSignal'))
                            break

                        self.emit(SIGNAL("userlogout"), res2[1])  # "用户已被注销!")
                        self.emit(SIGNAL("exitVm"), "", "exitAllVm")  # 关闭 window 窗口
                        self.emit(SIGNAL('hideRDPSignal'))  # 关闭 rdp 窗口
                        LogRecord.instance().logger.warn("session is Logout" + str(res2[1]))
                        # self.emit(SIGNAL("userlogout"), res2[1])#"用户已被注销!")
                        break
                    else:
                        # self.emit(SIGNAL('hideReconnectDlgSignal'))
                        # print UsbIp_Mgr.get_connected_ip()
                        pass

                except Exception as e:
                    LogRecord.instance().logger.error("vminfoUpdate:" + str(e.message))
                finally:
                    pass

        self.timer = Thread(target=vminfoUpdate)
        self.timer.setDaemon(True)  # 设置主线程为非守护线程
        # -------------------------------------------------

        # ======== 线程体函数 ============
        #        读取 管道 信息
        # ------------------------------
        def listen_vm_func():  #
            try:
                if not os.path.exists("/tmp/fifo1"):
                    os.system("mkfifo /tmp/fifo1")
                    LogRecord.instance().logger.info('mkfifo')
            except Exception as e:
                LogRecord.instance().logger.exception('make fifo exception!')
                # print e.message

            # f = None
            # try:
            #     f = open("/tmp/fifo1", 'r')
            # except Exception as e:
            #     print e.message

            while self.__listen_vm_run:
                try:
                    f = open("/tmp/fifo1", 'r')
                    msg = f.readline()
                    LogRecord.instance().logger.debug('msg::' + msg)
                    f.close()
                except Exception as e:
                    try:
                        f.close()
                    except:
                        LogRecord.instance().logger.exception('close fifo exception!')
                    LogRecord.instance().logger.exception('read fifo exception!')
                    # print e.message
                try:
                    msg, tmp = msg.split("\n", 1)
                except Exception, err:
                    msg = ''
                    LogRecord.instance().logger.exception('解析重启虚拟机管道信息异常！')
                    continue

                if msg == "exit":
                    break
                elif msg == "":
                    pass
                else:
                    vmid, cmd = msg.split(":")

                    LogRecord.instance().logger.info("recv pipe : [%s], [%s] " % (vmid, cmd))
                    # self.emit(SIGNAL("reset_vm"), vmid)
                    if cmd == "reboot":
                        self.emit(SIGNAL("oprateVm"), vmid, "reboot")
                    elif cmd == "poweroff":
                        self.emit(SIGNAL("oprateVm"), vmid, "poweroff")
                    elif cmd == "shutdown":
                        self.emit(SIGNAL("oprateVm"), vmid, "shutdown")
                    else:
                        self.emit(SIGNAL("oprateVm"), vmid, "poweroff")
                        LogRecord.instance().logger.info("other cmd : [%s], [%s] " % (vmid, cmd))




            # f.close()
            # os.remove("/tmp/fifo1")
            LogRecord.instance().logger.info("-------  listen_vm exit ------- ")

        self.listen_vm = Thread(target=listen_vm_func)
        self.listen_vm.setDaemon(True)  # 设置主线程为非守护线程
        # -------------------------------------------------

        for vmInfo in vmInfoList:
            LogRecord.instance().logger.debug('vmInfo::' + str(vmInfo))
            windesktopuint = WinDesktopUnit(userInfo, self.__centerIp, vmInfo)
            LogRecord.instance().logger.debug('windesktopuint::' + str(windesktopuint))
            self.connect(self, SIGNAL("for_screen_changed"), windesktopuint.update_style_function)
            self.connect(self, SIGNAL("vminfoUpdate"), windesktopuint.vminfoupdate)
            self.connect(self, SIGNAL("oprateVm"), windesktopuint.vmOprateSlot)  # 重启
            # self.connect(self, SIGNAL("reset_vm"), windesktopuint.for_vm_reset) # 重启
            self.connect(self, SIGNAL("enterVm"), windesktopuint.vmOprateSlot)  # 进入虚拟机
            self.connect(self, SIGNAL("exitVm"), windesktopuint.vmOprateSlot)  # 关闭 window
            self.connect(self, SIGNAL("USBPlugin"), windesktopuint.onUSBPlugin)  # 处理USB设备出入信号
            self.__desktopVirtListPut(windesktopuint)
            LogRecord.instance().logger.debug('__desktopVirtListPut')

        self.timer.start()
        self.listen_vm.start()

    def resetlayoutforvm(self):
        pass

    # 进入 默认虚拟机
    def enterDefaultVm(self, vmid):
        cmd = "enterVm"
        self.emit(SIGNAL("enterVm"), vmid, cmd)

    def update_screen_show(self):
        self.set_stylesheet_2()
        if self.stackedWidget.currentIndex() == 1:
            self.stackedWidget.setCurrentIndex(1)
            self.select_winapp()
        elif self.stackedWidget.currentIndex() == 0:
            self.stackedWidget.setCurrentIndex(0)
            self.select_windesktop()
        self.emit(SIGNAL("for_screen_changed"))

        # add by pbc for _change desktop layout -top
        # try:
        #     from common import common_run
        #     print common_run.SCREEN_WITH
        #     for i in range(7):
        #         if i >1:
        #             with_tmp = i* 200 + common_run.get_width(400)+ (i-1)* common_run.get_width(30.0)
        #             print with_tmp
        #             if with_tmp > common_run.SCREEN_WITH:
        #                 common_run.vm_colum = i-1
        #                 break
        #
        #     self.verticalLayout_2.removeItem(self.desktopGridLayout)
        #     self.desktopGridLayout = QtGui.QGridLayout()
        #     self.desktopGridLayout.setSizeConstraint(QtGui.QLayout.SetMinAndMaxSize)
        #     self.desktopGridLayout.setObjectName("desktopGridLayout")
        #     self.verticalLayout_2.addLayout(self.desktopGridLayout)
        #     self.showFullScreen()
        #     self.desktopGridLayout.setSpacing(common_run.get_width(20.0))
        #     self.desktopGridLayout.setContentsMargins(common_run.get_width(160),
        #                                           common_run.get_height(100),
        #                                           common_run.get_width(160),
        #                                           common_run.get_height(180))
        #
        #     for vmInfo in common_run.vmInfoList:
        #         windesktopuint = WinDesktopUnit(common_run.userInfo, self.__centerIp, vmInfo)
        #         self.connect(self, SIGNAL("vminfoUpdate"), windesktopuint.vminfoupdate)
        #         # self.connect(self, SIGNAL("reboot"), windesktopuint.vmReoot)
        #         self.connect(self, SIGNAL("reboot"), windesktopuint.vmOprateSlot) # 重启
        #         self.connect(self, SIGNAL("enterVm"), windesktopuint.vmOprateSlot) # 进入虚拟机
        #         self.connect(self, SIGNAL("exitVm"), windesktopuint.vmOprateSlot)   # 关闭 window
        #         self.__desktopVirtListPut(windesktopuint)
        # except:
        #     pass
        # self.set_stylesheet_2()
        # add by pbc for _change desktop layout -end

    @pyqtSlot()
    def settingdlog_show(self):
        _SettingDlg = SettingDlg(self.__vmInfoList)
        _SettingDlg.update_current_button_style()
        self.connect(_SettingDlg, SIGNAL("screen_change"), self.update_screen_show)
        _SettingDlg.exec_()
        # SettingDlg(self.__vmInfoList).exec_()

    @pyqtSlot()
    def winDebug_show(self):
        WinDebug().exec_()

    # ----------------------- API End-------------------------------------
    #  ------------------ 私有成员 -----------------------------------------
    def __setting_band_signalslot(self):
        self.connect(self.winDesktop, SIGNAL("clicked()"), self.__layout_band_winDesktop)
        self.connect(self.winApp, SIGNAL("clicked()"), self.__layout_band_winApp)

        self.connect(self.btn_logout, SIGNAL("clicked()"), self.__userLogoutShow)  # 注销 按钮
        self.connect(self, SIGNAL("userlogout"), self.__userBeLogout)  # 查询状态 用户被注销

        self.connect(self.btn_setting, SIGNAL("clicked()"), self.settingdlog_show)
        self.connect(self.btn_user, SIGNAL("clicked()"), self.__changePasswd_show)

        self.connect(self, SIGNAL("waitingdlgClose"), self.waitingdlg, SLOT("close()"))
        self.connect(self, SIGNAL("waitingdlgMsg"), self.waitingdlg_showMsg)
        self.connect(self, SIGNAL("showErrMsg"), self.showErrMsg)

    # 应用打印信息
    def __appbackInfo(self, code, description):
        if self._tmp_globel_sign == True:
            self._tmp_globel_sign = False
            if self.__appMsg_Shield == False:  # 当用户点击注销按钮,或者 被注销时 屏蔽 消息
                InfoDialog.instance().Information("提示", str(description))
            info = "[appbackinfo] : %s   %s" % (str(code), str(description))
            LogRecord.instance().logger.error(info)  # 日志
            self._tmp_globel_sign = True

    ## 追加 vm桌面
    def __desktopVirtListPut(self, vmDesktop):
        _com = common_run.vm_colum
        x = self.desktopGridLayout.count() % _com  # 第x列
        y = self.desktopGridLayout.count() / _com  # 第y行
        self.desktopGridLayout.addWidget(vmDesktop, y, x)

    def __desktopVirtListRemoveAll(self):  # 清空虚拟机显示
        LogRecord.instance().logger.debug("desktopGridLayout.count()::%d" % self.desktopGridLayout.count())
        while self.desktopGridLayout.count() > 0:
            _widget = self.desktopGridLayout.takeAt(0)
            layout = self.desktopGridLayout.removeItem(_widget)
            del layout

    @pyqtSlot()
    def __layout_band_winDesktop(self):
        self.stackedWidget.setCurrentIndex(0)
        self.select_windesktop()

    @pyqtSlot()
    def __layout_band_winApp(self):
        self.stackedWidget.setCurrentIndex(1)
        self.select_winapp()

    @pyqtSlot()
    def __changePasswd_show(self):
        self.__changePasswd.show()

    @pyqtSlot()
    def __userLogoutShow(self):

        retu = InfoDialog.instance().MessageBox(u'提示', u'您确定要注销登录吗?')  # choose yes or no
        if retu == "yes":
            self.__appMsg_Shield = True  # 应用消息屏蔽位
            self.__userLogoutfunc()

    # =========================================================
    # 查询状态,用户被注销
    # ---------------------------------------------------------
    def __userBeLogout(self, info="用户已经被注销"):  # 用户被注销
        self.__appMsg_Shield = True  # 应用消息屏蔽位

        # UsbIp_Mgr.usb_stop()  # 关闭usbip服务
        try:
            LogRecord.instance().logger.info("用户,被平台注销...")

            UsbIpManage2.usb_disconnect()  # 断开usb ip 连接
            UsbIpManage2.usbIpServer_stop()  # 停止 usb ip 服务
            UsbIpManage2.usbIpLogProcess_stop()  # 停止 usb ip 日志 服务

            self.__listen_vm_run = False
            if self.logout_thread != None:  # 如果点击注销 时, 被注销 同时发送,
                if self.logout_thread.isAlive():
                    self.logout_thread.join(5)

            self.timer.join(5)
            self.listen_vm.join(5)
            # UsbIp_Mgr.usbIpConnect_Stop()# 断开 usbIp 连接

            self.__detectUsb.stop()  # 停止USB设备监听

            # from messageDialog import MessageDialog
            # MessageDialog(str(info)).exec_()
            InfoDialog.instance().Information(u'提示', str(info))  # choose yes or no
            # MessageDialog("用户已经被注销").exec_()
        except Exception as e:
            info = str(e.message)
            LogRecord.instance().logger.error(info)
        finally:
            WinVirturlList.userloged = False
            self.emit(SIGNAL("winVirturlListClosed"))
            self.close()

    # ================================
    # 显示错误信息
    # --------------------------------
    @pyqtSlot()
    def showErrMsg(self, msg):
        # MessageDialog(str(msg)).exec_()
        InfoDialog.instance().Information(u'提示', str(msg))

    # ===========================
    # 进入虚拟机等待显示
    # ---------------------------
    @pyqtSlot()
    def waitingdlg_showMsg(self, msg):
        self.waitingdlg.showMsg(str(msg))

    @pyqtSlot()
    def __userLogoutfunc(self):

        LogRecord.instance().logger.info("启动注销...")
        logout = {"status": False, "info": ""}
        try:
            LogRecord.instance().logger.info("关闭 usbip server")

            UsbIpManage2.usb_disconnect()  # 断开usb ip 连接
            UsbIpManage2.usbIpServer_stop()  # 停止 usb ip 服务
            UsbIpManage2.usbIpLogProcess_stop()  # 停止 usb ip 日志 服务

            self.__thread_run = False
            self.__listen_vm_run = False
            print "---------------------- user logout ----------------"

            def logout_process():  # 进入虚拟机准备工作
                try:
                    sleep(2)
                    # 1.
                    self.timer.join(5)  # 等待 关闭 线程
                    self.listen_vm.join(5)  # 等待 关闭 线程

                    self.__detectUsb.stop()  # 停止USB设备监听

                    _userValidate = UserValidate(self.__userInfo, self.__centerIp)
                    res = _userValidate.logout()  # 发送注销命令

                    if res[0] == True:
                        print "发送注销命令成功"
                        cnt = 0
                        while True:
                            cnt = cnt + 1
                            sleep(1)
                            res2 = _userValidate.sessionIsLogout2()  # 查询状态
                            if res2[0] == True:  # 注销成功
                                break
                            else:
                                if cnt > 15:
                                    LogRecord.instance().logger.error("等待注销超时")
                                    logout["info"] = "等待注销超时"
                                    self.emit(SIGNAL("waitingdlgMsg"), "等待注销超时")
                                    sleep(5)
                                    # self.emit(SIGNAL("showErrMsg"), "查询注销超!")
                                    return
                            logout["status"] = True

                    else:
                        logout["info"] = res[1]
                        print "发送注销命令失败", res[1]
                        self.emit(SIGNAL("waitingdlgMsg"), "发送注销命令失败:" + res[1])
                        sleep(5)
                        #  self.emit(SIGNAL("showErrMsg"), "开机失败, 端口为空!")
                        return

                    sleep(0.1)

                except Exception as e:
                    logout["status"] = False, "注销异常"
                    LogRecord.instance().logger.exception("注销异常")
                finally:
                    print "关闭 等待窗口"
                    self.emit(SIGNAL("waitingdlgClose"))

            self.logout_thread = Thread(target=logout_process)
            self.logout_thread.setDaemon(True)  # 设置主线程为非守护线程
            self.logout_thread.start()
            # self.logout_thread.isAlive()
            self.waitingdlg.showMsg("正在注销...")
            self.waitingdlg.exec_()

        except Exception:
            LogRecord.instance().logger.exception("logout func")
        finally:
            WinVirturlList.userloged = False
            self.close()
            self.emit(SIGNAL("winVirturlListClosed"))
            return logout["status"], logout["info"]

    @pyqtSlot()
    def logout(self):  # 被 winLogin.py  clientLogout 调用

        res = self.__userLogoutfunc()
        if res[0] == True:
            return True, "注销成功"
        else:
            # return False, "注销失败"
            return res

    # ------------------ 私有成员 End---------------------------------------

    # 显示 调试窗口
    def keyPressEvent(self, e):
        if (e.modifiers() == Qt.ShiftModifier | Qt.ControlModifier) and (e.key() == Qt.Key_D):
            # print "ctrl + shilf + D"
            self.winDebug_show()


###############################
#   单元测试
##############################
if __name__ == "__main__":
    from PyQt4 import QtGui
    from os import environ

    environ["WIN_UI_IMAGES_PATH"] = "../../images"
    environ["MCOS_DESKTOP_RDP_DEBUG"] = "DESKTOP_RDP_DEBUG_ON"

    app = QtGui.QApplication([])

    vmInfo = {"name": "xp",
              "vmId": "123456",
              "osType": "REDHAT_64",
              "osStatus": "down",
              "vmIp": "192.168.137.1",
              "vmPort": "8888",
              "vmPassWd": "123456"
              }
    vmInfo2 = {"name": "win7",
               "vmId": "5555",
               "osType": "WINXP_32",
               "osStatus": "down",
               "vmIp": "192.168.137.1",
               "vmPort": "8888",
               "vmPassWd": "123456"
               }

    appInfo = {
        "appId": "123",
        "appName": "",
        "executablePath": ""
    }
    agentInfo = {
        "agentIp": "",
        "agentPort": "123"
    }

    userInfo = {
        "userName": "wr",
        "userPassword": "Pass1234",
        "userId": "123"
    }

    appInfoList = [appInfo, appInfo]

    appInfo["executablePath"] = "abc"

    vmInfoList = [vmInfo, vmInfo2]

    win = WinVirturlList()
    win.setUserLoginInfo(userInfo)
    win.desktopVirtListInit(vmInfoList)
    win.appVirtListInit(agentInfo, appInfoList)
    win.showMaximized()
    # win.showFullScreen()
    app.exec_()
