Exemplo n.º 1
20
class VMWidget(QWidget):
        
    def __init__(self,parent = None):
        super(VMWidget,self).__init__(parent)
        
        #self.setStyleSheet("QToolTip{background-color:white;color:black;font-size:12px;}")
        #self.setFont(QFont(u"微软雅黑",12))
        self.vmInfoList = []
        self.oldVmInfoList = [] 
        self.vmOffInfoList = []
        self.threadMap = {}
        self.processMap = {}
        self.parent = parent
        self.domainManager = DomainManager()
        self.progressMonitor = ProgressThread()
        self.vmstatusTimer = QTimer()
        #self.vmstatusTimer.start(7000)
        self.connect(self.vmstatusTimer, SIGNAL("timeout()"),self.postStatusToServer)
        self.startVmInfo = None
        if common.SCROLL_TYPE != "slider":
            self.scrollArea = QScrollArea(self)
            self.scrollArea.setStyleSheet("background-color:transparent;border:0px")
            self.vmButtonList = []
            self.vmTableWidget = QTableWidget()
            self.setTableWidgetStyle()
            
            self.mainLayout = QVBoxLayout()
            self.mainLayout.setMargin(0)
            self.mainLayout.setSpacing(0)
            self.mainLayout.addWidget(self.scrollArea)
            self.mainLayout.addSpacing(10)
        
            self.setLayout(self.mainLayout)
        
        
            self.downloadingList = []
        
            
            
        if common.SCROLL_TYPE == "slider":
            #三个自定义button,用于显示相应的虚拟机
            self.firstVM   = CustomVMButton(self)
            self.secondVM  = CustomVMButton(self)
            self.thirdVM   = CustomVMButton(self)
             
            self.vmButtonList = [self.firstVM, self.secondVM, self.thirdVM]
             
            for i in range(len(self.vmButtonList)):
                self.vmButtonList[i].setIcon(QIcon("images/windows.png"))
                self.vmButtonList[i].setIconSize(QSize(100,100))
                self.vmButtonList[i].setFlat(True)
                self.vmButtonList[i].setFont(QFont("Times", 15, QFont.Bold))
            
            #设置滑动条的样式
            self.slider = QSlider(Qt.Vertical,self)
            self.slider.setStyleSheet( "QSlider::groove:vertical {  "
                                        "border: 1px solid #4A708B;  "
                                        "background: #C0C0C0;  "
                                        "width: 5px;  "
                                        "border-radius: 1px;  "
                                        "padding-left:-1px;  "
                                        "padding-right:-1px;  "
                                        "padding-top:-1px;  "
                                        "padding-bottom:-1px;  "
                                        "}"
                                        "QSlider::handle:vertical {"
                                        "height: 100px;"
                                        "background: white;"
                                        "margin: 0 -4px;"
                                        "}" )
             
            self.btnLayout = QHBoxLayout(self)
            self.btnLayout.addStretch()
            self.btnLayout.addWidget(self.firstVM)
            self.btnLayout.addWidget(self.secondVM)
            self.btnLayout.addWidget(self.thirdVM)
            self.btnLayout.addStretch()
            self.btnLayout.addSpacing(10)
            self.btnLayout.addWidget(self.slider)
            self.btnLayout.setSpacing(10)
            self.btnLayout.setMargin(10)
             
            self.setLayout(self.btnLayout)
            
    def setTableWidgetStyle(self):
        
        #self.vmTableWidget.setColumnCount(3)
        #self.vmTableWidget.setRowCount(1)
        self.vmTableWidget.setFrameShape(QFrame.NoFrame)
        self.vmTableWidget.setEditTriggers(QTableWidget.NoEditTriggers)#不能编辑
        self.vmTableWidget.setSelectionMode(QAbstractItemView.NoSelection)
        self.vmTableWidget.verticalHeader().setVisible(False)#设置垂直头不可见
        self.vmTableWidget.horizontalHeader().setVisible(False)#设置垂直头不可见
        self.vmTableWidget.setShowGrid(False)
        self.vmTableWidget.setFocusPolicy(Qt.NoFocus)
        
        self.vmTableWidget.setStyleSheet("QTableWidget{background-color: rgb(235, 235, 235,0);}")    
    
    def getVmList(self):
        vmList = []
        vmInfo = {}
        vmInfo["name"] = "15615123021654541"
        vmInfo["status"] = "offline"
        vmInfo["name"] = "offline"
        vmInfo["os_distro"] = "windows_7"
        
        
        vmInfo1 = {}
        vmInfo1["name"] = "1561545421654541"
        vmInfo1["status"] = "offline"
        vmInfo1["name"] = "offline"
        
        vmInfo2 = {}
        vmInfo2["name"] = "1561afew21654541"
        vmInfo2["status"] = "offline"
        vmInfo2["name"] = "windows_7"
        
        vmInfo3 = {}
        vmInfo3["name"] = "afewfdsafewfa"
        vmInfo3["status"] = "offline"
        vmInfo3["name"] = "windows_7"
        
        vmList.append(vmInfo)
        vmList.append(vmInfo1)
        vmList.append(vmInfo2)
        vmList.append(vmInfo3)
        vmList.append(vmInfo1)
        vmList.append(vmInfo2)
        vmList.append(vmInfo3)
        
        return vmList
    def postStatusToServer(self):
        '''serverState = VMInfoManager.instance().getCurCloudServerState()
        if serverState != "enable":
            return'''
        postInfo = {}
        state = self.domainManager.getStatus()
        if self.vmOffInfoList == [] or len(self.downloadingList) != 0:
            #self.processMap.clear()
            #self.threadMap.clear()
            return
        if len(state) == 0:
            postInfo["state"] = "shutdown"
            postInfo["vmname"] = self.vmOffInfoList[0]["vmname"]
        else:
            for item in state:
                postInfo["state"] = "running"
                if state[item].has_key("disk_io"):
                    postInfo["io_throughput"] = state[item]["disk_io"]
                if state[item].has_key("max_disk_io"):
                    postInfo["io_throughput_peak"] = state[item]["max_disk_io"]
                if state[item].has_key("net_io"):
                    postInfo["net_throughput"] = state[item]["net_io"]
                if state[item].has_key("max_net_io"):
                    postInfo["net_throughput_peak"] = state[item]["max_net_io"]
                if state[item].has_key("memory_size"):
                    postInfo["memory"] = state[item]["memory_size"]*1024
                if state[item].has_key("vmname"):
                    postInfo["vmname"] = state[item]["vmname"]
                if state[item].has_key("name"):
                    postInfo["coursename"] = state[item]["name"]
                if state[item].has_key("cpu"):
                    postInfo["cpu_utilization"] = state[item]["cpu"]     
        self.emit(SIGNAL("vmstateinfo"),postInfo)
        
    def showVmList(self):
        subWidget = QWidget()
        if self.vmstatusTimer.isActive():
            pass
        else:
            #if globalvariable.CLASS_STATUS:
            self.vmstatusTimer.start(7000)
            #self.connect(self.vmstatusTimer, SIGNAL("timeout()"),self.postStatusToServer)
        
        if self.scrollArea.widget():
            self.scrollArea.takeWidget()
            
        self.vmTableWidget = QTableWidget()
        self.setTableWidgetStyle()
        #if self.vmTableWidget
        self.vmTableWidget.clear()
    
        #self.vmInfoList = self.getVmList()
        num = len(self.vmInfoList)
        columnCount = 1
        rowCount = 1
        if num == 0:
            return
        if num <=3:
            #self.scrollArea.verticalScrollBar().hide()
            rowCount = 1
            if num == 1:
                columnCount = 1
            elif num == 2:
                columnCount = 2
            elif num == 3:
                columnCount = 3
        else:
            rowCount = num/3
            rest = num%3
            if (rowCount == 2 and rest == 0)  or rowCount == 1 :
                pass
            if rest > 0:
                rowCount+=1
                
            columnCount = 3
        
        
        parentWidth = self.parent.width()
        resolutionValue = StoreInfoParser.instance().getResolutionValue()
        if resolutionValue:
            if len(resolutionValue.split("x")) >= 2:
                parentWidth = int(resolutionValue.split("x")[0])*5/9.0
        ratio = parentWidth/800.0
        tableWidth = (parentWidth - 20*2 -50*2*ratio)/3 + 5
        if len(self.vmInfoList) > 3:
            tableWidth = (parentWidth - 20*2 -50*2*ratio)/3 - 20*(1 - ratio) + 5
                
        self.vmTableWidget.setColumnCount(columnCount)
        self.vmTableWidget.setRowCount(rowCount)
        self.vmTableWidget.setFixedWidth(parentWidth-100)
        self.vmTableWidget.setFixedHeight((tableWidth+10)*rowCount)
        self.vmTableWidget.verticalHeader().setDefaultSectionSize(tableWidth+10)
        self.vmTableWidget.horizontalHeader().setDefaultSectionSize((parentWidth-100)/columnCount)
        #self.setWidget("status")
        if columnCount <= 3 and rowCount == 1:
            for i in range(columnCount):
                self.setRowColumnWidget(0,i,self.vmInfoList[i]["name"])
        else:
            for i in range(rowCount):
                for j in range(3):
                    if i*3 + j <= num-1:
                        self.setRowColumnWidget(i, j, self.vmInfoList[i*3+j]["name"])  
        
        mainLayout = QHBoxLayout()
        mainLayout.setMargin(0)
        mainLayout.addWidget(self.vmTableWidget)
        subWidget.setLayout(mainLayout)
        #if self.scrollArea.widget():
            #self.scrollArea.takeWidget()
        self.scrollArea.setWidget(subWidget) 
        self.scrollArea.setWidgetResizable(True) 
        #self.scrollArea.horizontalScrollBar().hide()   
    def setRowColumnWidget(self,row,column,vmid):
        status = "sfw"
        #self.vmTableWidget.clear()
        mainWidget = QWidget()
        #self.vmTableWidget.hideColumn()
        #vmRowButtonList = []
        parentWidth = self.parent.width()
        resolutionValue = StoreInfoParser.instance().getResolutionValue()
        if resolutionValue:
            if len(resolutionValue.split("x")) >= 2:
                parentWidth = int(resolutionValue.split("x")[0])*5/9.0
        ratio = parentWidth/800.0
        vmWidth = (parentWidth - 20*2 -50*2*ratio)/3
        if len(self.vmInfoList) > 3:
            vmWidth = (parentWidth - 20*2 -50*2*ratio)/3 - 20*(1 - ratio)
        
        vmButton = CustomVMButton()
        vmButton.setFixedSize(QSize(vmWidth, vmWidth + 5))
        vmButton.setIconSize(QSize(vmWidth - 60*ratio,vmWidth - 30*ratio))
        vmButton.setText(self.vmInfoList[row*3 + column]["name"])
        vmButton.setFlat(True)
        vmButton.setFont(QFont("Times", 15, QFont.Bold))
        vmInfo = self.vmInfoList[row*3 + column]
        vmButton.setVMInfo(vmInfo)
        imageName = "other.png"
        if self.vmInfoList[row*3 + column].has_key("os_distro"):
            if common.imageMap.has_key(self.vmInfoList[row*3 + column]["os_distro"]):
                imageName = common.imageMap[self.vmInfoList[row*3 + column]["os_distro"]]
            else:
                LogRecord.instance().logger.info(u'common.imageMap中未找到键值%s' % self.vmInfoList[row*3 + column]["os_distro"])
                        
        vmButton.setIcon(QIcon("images/systemImage/%s" % imageName))
                
#         if globalvariable.CLASS_STATUS and not globalvariable.TICHU_STATUS:
#             self.connect(vmButton, SIGNAL("clicked()"),self.slotOpenVMLesson)
#             self.connect(vmButton, SIGNAL("controlvm"),self.slotControlVM)
#         else:
#             self.connect(vmButton, SIGNAL("clicked()"),self.slotCreateVMLesson)
                    
        #vmRowButtonList.append(vmButton)
        self.vmButtonList.append(vmButton)
        #firMybutton.setStatus("undownload")
        vmButton.setObjectName(vmid + ":" + QString.number(row) + ":" + QString.number(column))
        self.connect(vmButton, SIGNAL("clicked()"),self.startDomain)
        
            
        progressBar = WidgetProgress()
        progressBar.setFixedSize(vmWidth, vmWidth + 5)
        #progressBar.progressBar.setValue(0)
        progressBar.setVmName(self.vmInfoList[row*3 + column]["name"])
        progressBar.setObjectName(vmid + ":" + QString.number(row) + ":" + QString.number(column))
        #progressBar.objectName()
        
        #self.firMybutton.setText(self.tr("确萨"))
        
        #progressBar = QProgressBar()
        
        myLayout = QHBoxLayout()
        myLayout.setMargin(0)
        myLayout.addStretch()
        myLayout.addWidget(vmButton)
        myLayout.addWidget(progressBar)
        myLayout.addStretch()
        
        if vmid in self.downloadingList:
            vmButton.hide()
        else:
            progressBar.hide()
             
        #firMybutton.hide()
        mainWidget.setLayout(myLayout)
        
        
        self.vmTableWidget.setCellWidget(row, column, mainWidget)
        #self.mainLayout.addWidget(mainWidget)  
    
    def setVMInfoList(self, vmInfoList, vmOffInfoList):
        
        self.oldVmInfoList = LocalImgManager.instance().getCompleteList()
        self.vmInfoList = vmInfoList
        self.vmOffInfoList = vmOffInfoList
        self.domainManager.deleteImgList(vmOffInfoList)
        
#         needDeleteList = self.compareDelete(self.oldVmInfoList, vmOffInfoList)
        if self.vmOffInfoList == []:
            #self.progressMonitor.stop()
            #self.threadMap.clear()
            for item in self.processMap:
                self.processMap[item].stop()
                if self.processMap[item].isRunning():
                    self.processMap[item].exit()
            for item in self.threadMap:
                if self.threadMap[item].isRunning():
                    self.threadMap[item].exit()
                
            self.processMap.clear()
            self.threadMap.clear()
            #self.killRsyncThread()
            
#         if len(needDeleteList) == 0:
#             return
#         else:
#             self.domainManager.deleteImgList(needDeleteList)
    def stopAllDownload(self):
        for item in self.processMap:
            self.processMap[item].stop()
            if self.processMap[item].isRunning():
                self.processMap[item].exit()
                
        self.killScpThread()
        for item in self.threadMap:
            #self.threadMap[item].stop()
            if self.threadMap[item].isRunning():
                self.threadMap[item].exit()
        
        self.downloadingList = []
        self.processMap.clear()
        self.threadMap.clear()
    def killScpThread(self):
        pidList = self.getScpsProcessId()
        #sshPidList = self.getSshProcessId()
        for item in pidList:
            self.killVmId(item)
        '''for mtem in sshPidList:
            self.killVmId(mtem)'''
        
    def killVmId(self,killid):
        cmd = "kill -9 " + killid
        os.system(str(cmd))
        
    def getScpsProcessId(self):#得到运行虚拟机的进程号序列,可用于关闭某个虚拟机
        
        idList = []
        cmd = "ps aux | grep scp"
        output = ""
        statusOutput = []
        statusOutput = commands.getstatusoutput(cmd)
        if statusOutput[0] == 0:
                output = statusOutput[1]
        else:
            output = ""
        result = output.split("\n")
        for i in range(len(result)):
            if QString(result[i]).contains("scp"):
                idList.append(QString(result[i]).simplified().split(" ")[1])
    
        return idList
    
    def getSshProcessId(self):#得到运行虚拟机的进程号序列,可用于关闭某个虚拟机
        
        idList = []
        cmd = "ps aux | grep /usr/bin/ssh"
        output = ""
        statusOutput = []
        statusOutput = commands.getstatusoutput(cmd)
        if statusOutput[0] == 0:
                output = statusOutput[1]
        else:
            output = ""
        result = output.split("\n")
        for i in range(len(result)):
            if QString(result[i]).contains("/usr/bin/ssh"):
                idList.append(QString(result[i]).simplified().split(" ")[1])
    
        return idList
    
    def compareDelete(self,oldList,newList):
        nameList = []
        deleteList = []
        for item in newList:
            nameList.append(item["name"])
            
        for name in oldList:
            if name not in nameList:
                deleteList.append(name)
        return deleteList
    
    def autoStartDownload(self):
        #return
        num = len(self.vmInfoList)
        if num == 0:
            return
        else:
            #self.progressMonitor.setVmInfoList(self.vmInfoList)
            #self.progressMonitor.start()
            #self.connect(self.progressMonitor, SIGNAL("downloadover"),self.slotDownloadOver)
            imgMap = LocalImgManager.instance().getCompliteListSize()
            for i in range(len(self.vmInfoList)):
                mark = 0
                for item in imgMap:
                    if item == self.vmInfoList[i]["name"] and imgMap[item] == self.vmInfoList[i]["img_file_size"]:
                        mark = 1
                if mark == 1:
                    continue
                row = i/3
                column = i%3
                self.downloadingList.append(self.vmInfoList[i]["name"])
#                 self.downloadThread = DownloadThread()
#                 self.progressThread = ProgressThread()
                threadid = self.vmInfoList[i]["name"] + ":" + QString.number(row) + ":" + QString.number(column)
#                 self.downloadThread.setProcessId(threadid + ":" + QString.number(self.vmInfoList[i]["img_file_size"]))
#                 self.progressThread.setProcessId(threadid + ":" + QString.number(self.vmInfoList[i]["img_file_size"]))
#                 self.connect(self.progressThread, SIGNAL("currentprogress"),self.updateProgressBar)
#                 self.connect(self.progressThread, SIGNAL("downloadover"),self.slotDownloadOver)
#                 self.downloadThread.start()
#                 self.progressThread.start()
                self.setRowColumnWidget(int(row), int(column), self.vmInfoList[i]["name"])
                self.createThread(threadid,self.vmInfoList[i])
                
                #time.sleep(1)
                #return
            self.startFirstThread()
    def startFirstThread(self):
        for item in self.threadMap:
            self.threadMap[item].start()
            self.processMap[item].start()
            self.connect(self.processMap[item], SIGNAL("currentprogress"),self.updateProgressBar)
            #self.connect(self.processMap[item], SIGNAL("downloadover"),self.slotDownloadOver)
            self.connect(self.threadMap[item], SIGNAL("downloadover"),self.slotDownloadOver)
            self.connect(self.threadMap[item], SIGNAL("downloaderror"),self.slotDownloadError)
            return
        
    def slotDownloadError(self,signalid):
        pass 
    
    def createThread(self,threadid,vmInfo):
        if self.threadMap.has_key(threadid):
            if self.threadMap[threadid].isRunning():
                self.threadMap[threadid].exit()
            self.threadMap.pop(threadid)
        if self.processMap.has_key(threadid):
            if self.processMap[threadid].isRunning():
                self.processMap[threadid].exit()
            self.processMap.pop(threadid)
        
        downloadThread = DownloadThread()
        progressThread = ProgressThread()
        self.threadMap[threadid] = downloadThread
        self.processMap[threadid] = progressThread
        self.threadMap[threadid].setProcessId(threadid + ":" + str(vmInfo["img_file_size"]))
        self.processMap[threadid].setProcessId(threadid + ":" + str(vmInfo["img_file_size"]))
        #self.threadMap[threadid].start()
        #self.processMap[threadid].start()
        #self.connect(self.processMap[threadid], SIGNAL("currentprogress"),self.updateProgressBar)
        #self.connect(self.processMap[threadid], SIGNAL("downloadover"),self.slotDownloadOver)
        
        
    def checkAddDownload(self):
        #return
        
        num = len(self.vmInfoList)
        #existImgList = LocalImgManager.instance().getCompleteList()
        existImgList = LocalImgManager.instance().getCompliteListSize()
        if num == 0:
            return
        else:
            count = 0
            for i in range(len(self.vmInfoList)):
                row = i/3
                column = i%3
                if existImgList.has_key(self.vmInfoList[i]["name"]) and existImgList.get(self.vmInfoList[i]["name"]) == self.vmInfoList[i]["img_file_size"]:
                    pass
                elif self.vmInfoList[i]["name"] in self.downloadingList:
                    pass
                elif existImgList.has_key(self.vmInfoList[i]["name"]) and self.domainManager.getDom() != None and self.startVmInfo != None and self.startVmInfo == self.domainManager.getDomainInfo():
                    pass
                else:
                    if self.vmInfoList[i]["name"] not in self.downloadingList:
                        self.downloadingList.append(self.vmInfoList[i]["name"])
                    threadid = self.vmInfoList[i]["name"] + ":" + QString.number(row) + ":" + QString.number(column)
                    self.createThread(threadid, self.vmInfoList[i])
                    self.setRowColumnWidget(int(row), int(column), self.vmInfoList[i]["name"])
                    count+= 1
                    
            if len(self.threadMap) == count:
                self.startFirstThread()
                if count > 0:
                    self.emit(SIGNAL("startadddownload"))
                
    def startDomain(self): 
        pbp = CustomVMButton().sender()
        buttonName = pbp.objectName()
        vmInfo = pbp.vmInfo
        for item in self.vmOffInfoList:
            if item["name"] == vmInfo["name"]:
                self.startVmInfo = item
        #return
    
        vmid = buttonName.split(":")[0]
        row = buttonName.split(":")[1]
        column = buttonName.split(":")[2]
        
        self.domainManager.setDomainInfo(self.startVmInfo)
        
        LogRecord.instance().logger.info(u"开始开启虚拟机-----------------------------------------------00")
        self.domainManager.startDomainByName()
        LogRecord.instance().logger.info(u"结束开启虚拟机-----------------------------------------------11")
        

    def updateProgressBar(self,count,objectname):
        #if self.threadMap[objectname].isRunning():
#         for i in range(len(self.downloadingList)):
#             if objectname == self.downloadingList[i]:
#                 progress=self.vmTableWidget.findChild((WidgetProgress, ),objectname)
#                 progress.progressBar.setValue(count) 
        progress=self.vmTableWidget.findChild((WidgetProgress, ),objectname)
        if not progress:
            return
        progress.progressBar.setValue(count) 
        
    def slotDownloadOver(self,count,name):
        serverState = VMInfoManager.instance().getCurCloudServerState()
        if serverState != "enable":
            return
        if self.processMap.has_key(name):
            self.processMap[name].stop()
        #self.processMap.pop(name)
        #self.threadMap.pop(name)
        vmid = name.split(":")[0]
        row = name.split(":")[1]
        column = name.split(":")[2]
        self.downloadingList = []
        self.setRowColumnWidget(int(row), int(column), vmid)
        time.sleep(4)
        if self.processMap.has_key(name) and self.processMap[name].isRunning:
            self.processMap[name].exit()
        if self.threadMap.has_key(name) and self.threadMap[name].isRunning:
            self.threadMap[name].exit()
        self.processMap.pop(name)
        self.threadMap.pop(name)
        self.emit(SIGNAL("avmdownloadover"))
#         for item in self.threadMap:
#             self.threadMap[item].start()
#             self.processMap[item].start()
#             self.connect(self.processMap[item], SIGNAL("currentprogress"),self.updateProgressBar)
#             self.connect(self.processMap[item], SIGNAL("downloadover"),self.slotDownloadOver)
#             return
    def getDownloadingList(self):
        return self.downloadingList
            
    def updateVMList(self):
        language = StoreInfoParser.instance().getLanguage()
        m_pTranslator = QTranslator()
        exePath = "./"
        if language == "chinese":
            QmName = "zh_CN.qm"
            StoreInfoParser.instance().setLanguage("chinese")
        else:
            QmName = "en_US.qm"
            
        if(m_pTranslator.load(QmName, exePath)):
            QCoreApplication.instance().installTranslator(m_pTranslator)
        
        if self.vmstatusTimer.isActive():
            self.vmstatusTimer.stop()
        else:
            pass
        subWidget = QWidget()
        vmNum = len(self.vmInfoList)
        rowNum = 0
        subMainLayout = QVBoxLayout()
        subMainLayout.setMargin(0)
        #subMainLayout.addStretch()
        #subMainLayout.addSpacing(10)
        #subMainLayout.setSpacing(10)
        
        self.vmButtonList = []
        
        if vmNum % 3 != 0:
            rowNum = vmNum / 3 + 1
        else:
            rowNum = vmNum / 3
             
        for i in range(rowNum):
            indexEnd = 3
            if i == rowNum - 1:
                indexEnd = vmNum - (i*3)
                 
            parentWidth = self.parent.width()
            resolutionValue = StoreInfoParser.instance().getResolutionValue()
            if resolutionValue:
                if len(resolutionValue.split("x")) >= 2:
                    parentWidth = int(resolutionValue.split("x")[0])*5/9.0
            
            ratio = parentWidth/800.0
            vmWidth = (parentWidth - 20*2 -50*2*ratio)/3
            if vmNum > 3:
                vmWidth = (parentWidth - 20*2 -50*2*ratio)/3 - 20*(1 - ratio)
            vmRowButtonList = []
            for j in range(indexEnd):
                vmButton = CustomVMButton(self)
                vmButton.setFixedSize(QSize(vmWidth, vmWidth + 5))
                vmButton.setIconSize(QSize(vmWidth - 60*ratio,vmWidth - 30*ratio))
                vmButton.setText(self.vmInfoList[i*3 + j]["name"])
                vmButton.setToolTip(self.tr("course: ") + self.vmInfoList[i*3 + j]["name"])
                vmButton.setStyleSheet(u"QToolTip{border-radius:5px;background-color:white;color:black;font-size:20px;font-family:微软雅黑;}")
                vmButton.setFlat(True)
                vmButton.setFont(QFont("Times", 15, QFont.Bold))
                vmInfo = self.vmInfoList[i*3 + j]
                vmButton.setVMInfo(vmInfo)
                imageName = "other.png"
                if self.vmInfoList[i*3 + j].has_key("os_distro"):
                    if common.imageMap.has_key(self.vmInfoList[i*3 + j]["os_distro"]):
                        imageName = common.imageMap[self.vmInfoList[i*3 + j]["os_distro"]]
                    else:
                        LogRecord.instance().logger.info(u'common.imageMap中未找到键值%s' % self.vmInfoList[i*3 + j]["os_distro"])
                        
                vmButton.setIcon(QIcon("images/systemImage/%s" % imageName))
                if globalvariable.CLASS_STATUS and not globalvariable.TICHU_STATUS:
                    self.connect(vmButton, SIGNAL("clicked()"),self.slotOpenVMLesson)
                    self.connect(vmButton, SIGNAL("controlvm"),self.slotControlVM)
                else:
                    self.connect(vmButton, SIGNAL("clicked()"),self.slotCreateVMLesson)
                    
                vmRowButtonList.append(vmButton)
                self.vmButtonList.append(vmButton)
              
            btnLayout = QHBoxLayout()
            if vmNum > 3:
                btnLayout.setSpacing(10)
                #btnLayout.setMargin(10)
                btnLayout.addSpacing(30)
            for vmbtn in vmRowButtonList:
                btnLayout.addWidget(vmbtn)
            btnLayout.addStretch()
            subMainLayout.addLayout(btnLayout) 
             
        #subMainLayout.addStretch()
        subWidget.setLayout(subMainLayout)
        if self.scrollArea.widget():
            self.scrollArea.takeWidget()
        self.scrollArea.setWidgetResizable(False)
        self.scrollArea.setWidget(subWidget)
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    def startVM(self):
        return  
        
    def autoOpenVMLesson(self, vmName, allflag = False):
        LogRecord.instance().logger.info(u'自动打开相应的虚拟机')
        if self.vmButtonList:
            vmInfo = self.vmButtonList[0].getVMInfo()
            VMOperation.instance().setCurrentVMInfo(vmInfo)
            #thread.start_new_thread(VMOperation.instance().openVM,())
            if allflag == True:                      
                if VMOperation.instance().openVM():
                    LogRecord.instance().logger.info(u'start the lesson')  
            else:
                if VMOperation.instance().openVM():
                    LogRecord.instance().logger.info(u'start the lesson')  
        else:
            LogRecord.instance().logger.info(u'未监测到虚拟机%s的信息' % vmName)  
    
    def autoOpenOffVMLesson(self):
        LogRecord.instance().logger.info(u'自动打开相应的虚拟机')
        
        if len(self.vmInfoList) == 1:
            if self.vmInfoList[0]["name"] in self.downloadingList:
                return
            else:
                self.startVmInfo = self.vmInfoList[0]
                self.domainManager.setDomainInfo(self.startVmInfo)
                self.domainManager.startDomainByName()
        
        else:
            return
    def checkDownloadOver(self):
        if self.autoCourse in self.downloadingList:
            pass    
        else:
            self.courseTimer.stop()
            #self.autoCourse = ""
            for item in self.vmOffInfoList:
                if self.autoCourse == item["name"]:
                    vmInfo = item
                    self.domainManager.setDomainInfo(vmInfo)
                    self.domainManager.startDomainByName()
                    return
            
    def autoOpenCourse(self,name,classid = None):
        LogRecord.instance().logger.info(u'自动打开相应的虚拟机')
        self.autoCourse = name
        if name in self.downloadingList:
            self.courseTimer = QTimer()
            self.courseTimer.start(1000)
            self.connect(self.courseTimer, SIGNAL("timeout()"),self.checkDownloadOver)
        
        else:
            for item in self.vmOffInfoList:
                if name == item["name"]:
                    vmInfo = item
                    if classid != None:
                        vmInfo["classid"] = classid
                
                    self.domainManager.setDomainInfo(vmInfo)
                    self.domainManager.startDomainByName()
                    
                    return
                
    def slotCreateVMLesson(self):
        vmBtn = self.sender()
        if vmBtn:
            LogRecord.instance().logger.info(u'开始创建虚拟机')
            if globalvariable.VM_IS_CREATE_STATUS:
                LogRecord.instance().logger.info(u'重复点击!')
                return
            else:
                globalvariable.VM_IS_CREATE_STATUS = True

            LogRecord.instance().logger.info(u'准备获取虚拟机信息!')
            paramInfo = vmBtn.getVMInfo()
            LogRecord.instance().logger.info(u'准备获取虚拟机信息完成!')
            try:
                vmName = VMOperation.instance().createVMLesson(paramInfo)
            except:
                LogRecord.instance().logger.info(u'创建虚拟机异常.........!')
            LogRecord.instance().logger.info(u'得到创建的虚拟机信息!')
            if vmName:
                LogRecord.instance().logger.info(u'创建虚拟机%s成功' % vmName)
                vmInfo = NetworkManager.instance().getVMInfo(vmName)
                if vmInfo == None:
                    globalvariable.VM_IS_CREATE_STATUS = False
                    return
                if len(vmInfo) == 0:
                    globalvariable.VM_IS_CREATE_STATUS = False
                    return
                vmInfo[0]["vmname"] = vmInfo[0]["name"]
                if vmInfo:
                    VMOperation.instance().setCurrentVMInfo(vmInfo[0])
                    if VMOperation.instance().openVM(True):
                        #保存开启虚拟机的名称
                        #globalvariable.VM_IS_CREATE_STATUS = False
                        WindowMonitor.instance().insertVmId(vmName)
                    else:
                        globalvariable.VM_IS_CREATE_STATUS = False
                        #删除没有成功运行的虚拟机
                        if VMOperation.instance().removeVMLesson(vmName):
                            LogRecord.instance().logger.info(u"删除后台相应的虚拟机成功")
                else:
                    LogRecord.instance().logger.info(u'未查询到相应的虚拟机:%s' % vmName)
                    globalvariable.VM_IS_CREATE_STATUS = False
            else:
                LogRecord.instance().logger.info(u'创建虚拟机失败')
                globalvariable.VM_IS_CREATE_STATUS = False


            #刷新虚拟机界面
            self.emit(SIGNAL("refreshVMS"))


    def slotControlVM(self, action):
        vmBtn = self.sender()
        if vmBtn:
            vmInfo = vmBtn.getVMInfo()
            VMOperation.instance().setCurrentVMInfo(vmInfo)
            VMOperation.instance().controlVM(action)
            
            vmInfos = globalvariable.VM_INFO
            self.setVMInfoList(vmInfos,[])
            self.updateVMList()

        
    def slotOpenVMLesson(self):
        #vmInfo = []
        vmBtn = self.sender()
        if vmBtn:
            btnVMInfo = vmBtn.getVMInfo()
            VMOperation.instance().setCurrentVMInfo(btnVMInfo)
            VMOperation.instance().openVM(True)
            
#         if globalvariable.CLASS_STATUS:
#             vmInfo = globalvariable.VM_INFO
#         else:
#             vmInfo = VMInfoManager.instance().getLessonListInfo()
#             
        #self.setVMInfoList(vmInfo,[])
        #self.updateVMList()
    #slider        
    def setSliderMaxValue(self, value):
        """设在滑动条的最大值"""
        maxValue = 1
        if value % 3 == 0:
            maxValue = (value / 3)
        else:
            maxValue = (value / 3 + 1)
         
        maxValue = maxValue - 1
         
        self.slider.setMinimum(1)
        self.slider.setMaximum(maxValue*3)
        self.slider.setValue(self.slider.maximum())
        self.currentIndex = maxValue
        self.maxValue = maxValue
        self.updateVMList()
        
    def paintEvent(self,event):
        if common.SCROLL_TYPE == "slider":
            self.setNodeSize(QSize(self.geometry().width()*4/15,self.geometry().height()*4/9))
        elif len(self.vmInfoList) <= 6:
            subWidget = self.scrollArea.widget()
            if subWidget != None:
                if len(self.vmInfoList) <= 3:
                    subWidget.move((self.geometry().width() - subWidget.width())/2, (self.geometry().height() - subWidget.height())/2 - 20)
                else:
                    subWidget.move((self.geometry().width() - subWidget.width())/2 - 15, (self.geometry().height() - subWidget.height())/2)
        QWidget.paintEvent(self, event)
    
    #slider               
    def setNodeSize(self,size):
        self.btnLayout.setSpacing(size.width()/20)
        self.btnLayout.setMargin(size.width()*3/20)
        
        self.firstVM.setIconSize(size)
        self.secondVM.setIconSize(size)
        self.thirdVM.setIconSize(size)
        
        self.slider.resize(QSize(self.slider.frameGeometry().width(),self.height()-100))
        
    def wheelEvent(self,event):
        """鼠标滚轮滚动事件,显示对应的虚拟机"""
        if common.SCROLL_TYPE == "slider":
            if event.delta() < 0 and self.currentIndex > 0:
                self.currentIndex -= 1
                self.updateVMListSlider()
            elif event.delta() > 0 and self.currentIndex < self.maxValue:
                self.currentIndex += 1
                self.updateVMListSlider()
   
            self.slider.wheelEvent(event)
        else:
            maxValue = self.scrollArea.verticalScrollBar().maximum()
            minValue = self.scrollArea.verticalScrollBar().minimum()
            currentValue = self.scrollArea.verticalScrollBar().value()
            if event.delta() < 0 and currentValue < maxValue:
                self.scrollArea.wheelEvent(event)
            elif event.delta() > 0 and currentValue > minValue:
                self.scrollArea.wheelEvent(event)
        
    #slider     
    def updateVMListSlider(self):
        """更新虚拟机列表"""
        for i in range(len(self.vmButtonList)):
            self.vmButtonList[i].hide()
 
        vmsInfoList = VMInfoManager.instance().getVMSInfo()
        if vmsInfoList:
            self.slider.show()
            startIndex = (self.maxValue - self.currentIndex) * 3
             
            if startIndex/3 == (self.maxValue):
                endIndex = len(vmsInfoList)
            else:
                endIndex = startIndex + 3
                 
            for i in range(startIndex, endIndex):
                self.vmButtonList[i - startIndex].setText(vmsInfoList[i])
                self.vmButtonList[i - startIndex].show()  
        else:
            self.slider.hide()
         
            
            
    """      echo <graphics type='sdl display='$DISPLAY' xauth='$XAUTHORITY'/>
Exemplo n.º 2
0
class K800IRec(QWidget, mfso):
    def __init__(self):
       mfso.__init__(self, "K800i-Recover")
       self.name = "K800i-Recover"
       self.icon = None
       self.__disown__()

    def start(self, args):
        self.vfs = vfs.vfs()
        self.dumpnumber = 1
        try :
          self.nor = args['nor'].value()
          self.nand = args['nand'].value()
        except IndexError:
	  return
        try:
          self.spareSize = args["spare-size"].value()
        except IndexError:
          self.spareSize = 16
        try:
          self.pageSize = args["page-size"].value()
        except IndexError:
	  self.pageSize = 512
        self.k800n = Node("k800-base")
        self.k800n.__disown__()
        self.boot = SEBootBlock(self.nor, self.pageSize) 
        self.blockSize = self.boot.blockSize
        self.nandClean = SpareNode(self,  self.nand, "nandfs", self.pageSize, self.spareSize, self.k800n)
        self.norFs = NorFs(self, self.k800n,  self.nor, "norfs", self.boot)
        self.fullFs = FullFs(self, self.k800n, self.norFs, self.nandClean, "fullfs", self.boot)
        self.gdfs = GDFS(self, self.k800n, self.nor, "gdfs", self.boot)
        self.firmware = Firmware(self, self.k800n,  self.nor, "firmware", self.boot.norfsoffset)

        self.tables = Tables(self.fullFs, self.blockSize)
        self.registerTree(self.nand, self.k800n)
 
    def createDump(self):
       text, ok = QInputDialog.getText(self, "Create dump", "dump name:", QLineEdit.Normal, "k800-restore-" + str(self.dumpnumber)) 
       if ok and text != "":
         if  (self.vfs.getnode(self.nand.absolute() + "/" + str(text)) == None):  
           self.dumpnumber += 1
           newroot = Node(str(text))
	   newroot.__disown__()
	   for id in range(0, len(self.tables.tablesIdWriteMap) - 1):
             write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16)
             self.tables.map[id] = self.tables.tablesIdWriteMap[id][write]
           virtual = VirtualMap(self, newroot, self.fullFs, self.tables, "virtual", self.blockSize)
           separt = SEPartitionBlock(virtual, self.boot.partitionblock, self.blockSize)
           self.createPart(separt, newroot, virtual)
           self.registerTree(self.nand, newroot) 
         else :
          box = QMessageBox(QMessageBox.Warning, "Error", "Error node already exists", QMessageBox.NoButton, self)
          box.exec_()
          self.createDump()

    def createPart(self, separt, newroot, virtual):
      for part in separt.partTable:
       if part.start > 0:
         p = Partition(self, newroot, virtual, part, self.blockSize)

    def g_display(self):
      QWidget.__init__(self, None)
      self.layout = QVBoxLayout(self)
      self.hlayout = QSplitter(self)
      self.layout.insertWidget(0, self.hlayout)
      self.layout.setStretchFactor(self.hlayout, 1)
      self.gTable()
      self.viewTable()

      self.button = QPushButton("&Create dump")
      self.connect(self.button, SIGNAL("clicked()"), self.createDump)
      self.layout.addWidget(self.button)
     	

    def viewTable(self):
      self.vtable = QTableWidget() 
      self.vtable.setColumnCount(20)	
      self.vtable.setRowCount(48)
      self.hlayout.addWidget(self.vtable)
 
    def viewTableUpdate(self, id):
      write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16) 
      t = self.tables.tablesIdWriteMap[id][write]
      l = t.blockList
      for x in xrange(0, len(t.blockList[0])):
        block = t.blockList[0][x]
        c = ((x) % 20) 
        r = ((x) / 20) 
        item = QTableWidgetItem(QString(hex(block))) 
        tipBlock = (id * 960) + x
        item.setToolTip(QString(hex(tipBlock)))
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.vtable.setItem(r ,c,  item)
     

    def gTable(self):
      self.gtable = QTableWidget()
      self.gtable.setColumnCount(1)	
      self.gtable.setRowCount(len(self.tables.tablesIdWriteMap))
      self.gtable.setHorizontalHeaderItem(0, QTableWidgetItem(QString("version")))
      self.hlayout.addWidget(self.gtable)
      self.sigMapper = QSignalMapper(self)
      for id in self.tables.tablesIdWriteMap:
         wlist = self.tables.tablesIdWriteMap[id]
         cbox = QComboBox(self.gtable)
         self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper, SLOT("map()"))
         self.sigMapper.setMapping(cbox, id)
         l = [] 
         for write in wlist:
           l.append(write)
         l.sort()
         l.reverse()
         for write in l:
	   cbox.addItem(QString(hex(write))) 
	 self.gtable.setCellWidget(id, 0, cbox)
	 self.gtable.setVerticalHeaderItem(id, QTableWidgetItem(QString(hex(id))))
      self.connect(self.sigMapper, SIGNAL("mapped(int)"),  self.viewTableUpdate) 
      self.gtable.setMaximumWidth(self.gtable.columnWidth(0) + self.gtable.verticalHeader().sectionSize(0) + 30)  
 
    def updateWidget(self):
       pass 
Exemplo n.º 3
0
class PvTunerDlg(QDialog):
    COL = 6
    COL_ELEMENT = 0
    COL_FIELD = 1
    COL_PV = 2
    COL_STEPSIZE = 3
    COL_READBACK = 4
    COL_SETPOINT = 5
    FMT_READBACK = "%.4e"

    def __init__(self, parent=None):
        super(PvTunerDlg, self).__init__(parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        #self.inputBox = QLineEdit("PL2G2C01A.x")
        #self.inputBox = QLineEdit("CXH2G6C01B.x")
        self.inputBox = QLineEdit("PL2G2C01A")

        addPvBtn = QPushButton("add")

        self.table = QTableWidget(0, PvTunerDlg.COL)
        self.table.setHorizontalHeaderLabels(
            ["Element", "Field", "PV", "Stepsize", "Readback", "setpoint"])
        #self.table.horizontalHeader().setStretchLastSection(True)
        #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)

        box = QGridLayout()
        box.addWidget(self.inputBox, 0, 0)
        box.addWidget(addPvBtn, 0, 1)
        box.addWidget(self.table, 1, 0, 1, 2)
        box.addWidget(buttonBox, 2, 0)

        self.setLayout(box)

        self.pvs_rb = []
        self.pvs_rb_val_flat = []
        self.pvs_sp = []
        self.pvmoni = []
        self.spinbox = []
        self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv)
        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv)
        self.connect(buttonBox.button(QDialogButtonBox.Ok),
                     SIGNAL("clicked()"), self.close)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"),
                     self._cell_clicked)

    def _cell_clicked(self, row, column):
        #print row, column
        if column in [self.COL_PV, self.COL_STEPSIZE]:
            item = self.table.item(row, column)
            if not item: return
            item.setFlags(item.flags() | Qt.ItemIsEditable)

    def _appendRecord(self, name):
        vec = name.split('.')
        if len(vec) > 2:
            QMessageBox.critical(None, "ERROR", "format is wrong")
            return

        if len(vec) == 1:
            elem, field = vec[0], 'value'
        elif len(vec) == 2:
            elem, field = vec

        elemobj = hla.getElements(elem)
        if elemobj:
            # pvsrb is a list
            pvsrb = elemobj.pv(field=field, handle='readback')
            self.pvs_rb.append(pvsrb)
            pvssp = elemobj.pv(field=field, handle='setpoint')
            self.pvs_sp.append(pvssp)
        else:
            QMessageBox.critical(None, "ERROR", "element %s not found" % elem)
            return

        # expand one row
        m, n = self.table.rowCount(), self.table.columnCount()
        self.table.insertRow(m)

        # add cells
        item = QTableWidgetItem(elem)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_ELEMENT, item)

        item = QTableWidgetItem(field)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_FIELD, item)

        item = QTableWidgetItem(', '.join(pvsrb))
        #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        self.table.setItem(m, self.COL_PV, item)

        readval = ['%.4e' % v for v in caget(pvsrb)]
        item = QTableWidgetItem(', '.join(readval))
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_READBACK, item)

        # set the stepsize of PV
        stepsize = 0.00001
        if pvssp:
            item = QTableWidgetItem('%f' % stepsize)
            item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(m, self.COL_STEPSIZE, item)

            self.spinbox.append(QDoubleSpinBox(self.table))
            self.spinbox[-1].setRange(-100, 100)
            #self.spinbox[-1].setValue(float(10.0))
            self.spinbox[-1].setSingleStep(stepsize)
            self.spinbox[-1].setDecimals(10)

            self.spinbox[-1].valueChanged.connect(self._writePv)

            self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1])

            sp = float(caget(pvssp)[0])
            #print "setpoint:", pvssp, sp, type(sp)
            self.spinbox[-1].setValue(-1e-5)
            #print "connected", self.spinbox[-1].value()
        else:
            item = self.table.item(m, self.COL_STEPSIZE)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            item = self.table.item(m, self.COL_SETPOINT)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.spinbox.append(None)

        self.table.resizeColumnsToContents()

    def addPv(self):
        self._appendRecord(str(self.inputBox.text()))
        self._updateMonitors()

    def minimalSizeHint(self):
        return QSize(800, 600)

    def _writePv(self, v):
        """
        """
        c = QObject.sender(self)
        i = self.spinbox.index(c)
        #print i, c.text(), "changed"

        #print self.pvs_sp[i], v
        caput(self.pvs_sp[i], v)

    def _updateMonitors(self):
        """
        prepare the PV list for camonitor
        """
        #print "Updating monitors"
        pvs = []
        self.pvs_rb_val = []
        for i in range(self.table.rowCount()):
            for j in range(len(self.pvs_rb[i])):
                self.pvs_rb_val.append([i, 0.0])
            pvs.extend(self.pvs_rb[i])

        for p in self.pvmoni:
            p.close()
        self.pvmoni = camonitor(pvs, self._updatePvValues)
        #print self.pvmoni
        #print pvs
        #print self.pvs_rb_val

    def _updatePvValues(self, val, idx):
        #print idx, val
        s = []
        for i, v in enumerate(self.pvs_rb_val):
            if v[0] == self.pvs_rb_val[idx][0]:
                s.append(self.FMT_READBACK % val)
        #print s
        item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK)
        item.setText(','.join(s))

    def closePvMonitors(self):
        #print "Closing PV Monitors"
        for p in self.pvmoni:
            p.close()

        pass

    def closeEvent(self, event):
        self.closePvMonitors()
        event.accept()

    def close(self):
        self.closePvMonitors()
        return True
Exemplo n.º 4
0
class Widget(QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        buttonHelp1 = QPushButton('help')
        buttonHelp1.setEnabled(False)
        buttonHelp1.setToolTip('The table below, with the exception of the last row and column, describe the network\n' +
                               'in terms of the weight coefficient values. The value of a cell in the n-th row and m-th\n' +
                               'column is the weight of the n-th feature for the m-th animal class.\n\n' +
                               'As you can see, each animal class has its own neuron that recognizes it, and each of\n' +
                               'these neurons has inputs that receive individual feature values.\n\n' +
                               'The last column represents the input vector, and the last row contains the network\n' +
                               'output values.')
        buttonHelp2 = QPushButton('help')
        buttonHelp2.setEnabled(False)
        buttonHelp2.setToolTip('If you show the winner, you will see the neuron whose response was the strongest.\n' +
                               'This neuron indicates the animal class the examined object will most probably fall into.\n' +
                               'The table below, with the exception of the last row and column, describe the network\n' +
                               'in terms of the weight coefficient values. The value of a cell in the n-th row and m-th\n' +
                               'column is the weight of the n-th feature for the m-th animal class.\n\n' +
                               'As you can see, each animal class has its own neuron that recognizes it, and each of\n' +
                               'these neurons has inputs that receive individual feature values.\n\n' +
                               'The last column represents the input vector, and the last row contains the network\n' +
                               'output values.')

        hBoxLayout1 = QHBoxLayout()
        hBoxLayout1.addWidget(QLabel('The neural network in this example uses five features to recognize\n' +
                                     'three classes of animals. Its weight coefficients are predefined and shown in the table below.\n\n' +
                                     'To test the network behavior, enter the input signals in the rightmost column and read the output\n' +
                                     'values from the bottom row.'))
        hBoxLayout1.addWidget(buttonHelp1)

        self.checkBoxWinner = QCheckBox()
        self.checkBoxWinner.setText('Show the winner')

        hBoxLayout2 = QHBoxLayout()
        hBoxLayout2.addWidget(self.checkBoxWinner)
        hBoxLayout2.addWidget(buttonHelp2)

        self.tableWidget = QTableWidget()
        self.labelNeuron = QLabel('(There is no winner.)')
        self.labelType = QLabel('This is something strange!')
        self.spinBoxThreshold = QDoubleSpinBox()
        self.spinBoxThreshold.setValue(5.0)

        self.groupBox = QGroupBox('Show the winner')
        gridLayout = QGridLayout()
        gridLayout.addWidget(QLabel('And the winner is...'), 0, 0)
        gridLayout.addWidget(self.labelNeuron, 0, 1)
        gridLayout.addWidget(QLabel('Because of this, the network claims:'), 1, 0)
        gridLayout.addWidget(self.labelType, 1, 1)
        gridLayout.addWidget(QLabel('Threshold:'), 2, 0)
        gridLayout.addWidget(self.spinBoxThreshold, 2, 1)
        self.groupBox.setLayout(gridLayout)
        self.groupBox.setVisible(False)

        vBoxLayout = QVBoxLayout()
        vBoxLayout.addLayout(hBoxLayout1)
        vBoxLayout.addWidget(self.tableWidget)
        vBoxLayout.addLayout(hBoxLayout2)
        vBoxLayout.addWidget(self.groupBox)

        self.setLayout(vBoxLayout)
        self.setWindowTitle('Simple linear neural network (example2)')

        self.classNames = ['mammal', 'bird', 'fish']

        self.tableWidget.setColumnCount(5)
        self.tableWidget.setRowCount(6)
        self.tableWidget.verticalHeader().hide()
        self.tableWidget.setHorizontalHeaderLabels(['Feature'] + self.classNames +  ['Input vector'])
        self.tableWidget.setCellWidget(0, 0, QLabel('number of legs'))
        self.tableWidget.setCellWidget(1, 0, QLabel('lives in water'))
        self.tableWidget.setCellWidget(2, 0, QLabel('can fly'))
        self.tableWidget.setCellWidget(3, 0, QLabel('has feathers'))
        self.tableWidget.setCellWidget(4, 0, QLabel('egg-laying'))
        self.tableWidget.setCellWidget(5, 0, QLabel('Output'))

        weights = [
            [   4,     0.01,   0.01,   -1,     -1.5 ],
            [   2,     -1,     2,      2.5,    2    ],
            [   -1,    3.5,    0.01,   -2,     1.5  ]
        ]

        for i in xrange(len(weights)):
            for j in xrange(len(weights[i])):
                self.tableWidget.setCellWidget(j, i + 1, QLabel('    ' + str(weights[i][j])))
        for i in xrange(len(weights)):
            self.tableWidget.setCellWidget(5, i + 1, QLabel(''))
        for i in xrange(len(weights[0])):
            doubleSpinBox = QDoubleSpinBox()
            doubleSpinBox.setValue(0.0)
            doubleSpinBox.setRange(-15.0, 15.0)
            self.tableWidget.setCellWidget(i, 4, doubleSpinBox)
        self.tableWidget.setCellWidget(5, 4, QPushButton('Calculate'))
        self.linearNetwork = LinearNetwork(initialWeights=weights)
        self.connect(self.checkBoxWinner, SIGNAL('stateChanged(int)'), self.visibleGrid)
        self.connect(self.tableWidget.cellWidget(5, 4), SIGNAL('clicked()'), self.updateResult)
        self.resize(600, 400)

    def visibleGrid(self, state):
        if state == 0:
            self.groupBox.setVisible(False)
        else:
            self.groupBox.setVisible(True)
            self.updateResult()

    def updateResult(self):
        inputColumn0 = self.tableWidget.cellWidget(0, 4).value()  # number of legs
        inputColumn1 = self.tableWidget.cellWidget(1, 4).value()  # lives in water
        inputColumn2 = self.tableWidget.cellWidget(2, 4).value()  # can fly
        inputColumn3 = self.tableWidget.cellWidget(3, 4).value()  # has feathers
        inputColumn4 = self.tableWidget.cellWidget(4, 4).value()  # egg-laying

        outputVector = self.linearNetwork.response([inputColumn0, inputColumn1, inputColumn2, inputColumn3, inputColumn4])

        if self.checkBoxWinner.checkState() == Qt.Checked:
            winner = LinearNetwork.winner(outputVector, self.spinBoxThreshold.value())
            for i in xrange(len(outputVector)):
                self.tableWidget.setCellWidget(5, i + 1, QLabel())
            if winner != -1:
                cellWinner = self.tableWidget.cellWidget(5, winner + 1)
                cellWinner.setStyleSheet('background-color: red;')

                self.labelNeuron.setText('Neuron ' + str(winner + 1))
                self.labelType.setText('This is a ' + self.classNames[winner])
            else:
                self.labelNeuron.setText('(There is no winner.)')
                self.labelType.setText('Thiss is something strange!')

        for i in xrange(len(outputVector)):
            self.tableWidget.cellWidget(5, i + 1).setText(str(outputVector[i]))
Exemplo n.º 5
0
class PvTunerDlg(QDialog):
    COL = 6
    COL_ELEMENT  = 0
    COL_FIELD    = 1
    COL_PV       = 2
    COL_STEPSIZE = 3
    COL_READBACK = 4
    COL_SETPOINT = 5
    FMT_READBACK = "%.4e"
    def __init__(self, parent=None):  
        super(PvTunerDlg, self).__init__(parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        #self.inputBox = QLineEdit("PL2G2C01A.x")
        #self.inputBox = QLineEdit("CXH2G6C01B.x")
        self.inputBox = QLineEdit("PL2G2C01A")

        addPvBtn = QPushButton("add")

        self.table = QTableWidget(0, PvTunerDlg.COL)
        self.table.setHorizontalHeaderLabels(["Element", "Field", "PV",
                 "Stepsize", "Readback", "setpoint"])
        #self.table.horizontalHeader().setStretchLastSection(True)
        #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)

        box = QGridLayout()
        box.addWidget(self.inputBox, 0, 0)
        box.addWidget(addPvBtn, 0, 1)
        box.addWidget(self.table, 1, 0, 1, 2)
        box.addWidget(buttonBox, 2, 0)

        self.setLayout(box)

        self.pvs_rb = []
        self.pvs_rb_val_flat = []
        self.pvs_sp = []
        self.pvmoni = []
        self.spinbox = []
        self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv)
        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv)
        self.connect(buttonBox.button(QDialogButtonBox.Ok),
                     SIGNAL("clicked()"), self.close)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"),
                     self._cell_clicked)


    def _cell_clicked(self, row, column):
        #print row, column
        if column in [self.COL_PV, self.COL_STEPSIZE]:
            item = self.table.item(row, column)
            if not item: return
            item.setFlags(item.flags() | Qt.ItemIsEditable)

    def _appendRecord(self, name):
        vec = name.split('.')
        if len(vec) > 2:
            QMessageBox.critical(None, "ERROR", "format is wrong")
            return

        if len(vec) == 1:
            elem, field = vec[0], 'value'
        elif len(vec) == 2:
            elem, field = vec

        elemobj = hla.getElements(elem)
        if elemobj:
            # pvsrb is a list
            pvsrb = elemobj.pv(field=field, handle='readback')
            self.pvs_rb.append(pvsrb)
            pvssp = elemobj.pv(field=field, handle='setpoint')
            self.pvs_sp.append(pvssp)
        else:
            QMessageBox.critical(None, "ERROR", "element %s not found" % elem)
            return

        # expand one row
        m, n = self.table.rowCount(), self.table.columnCount()
        self.table.insertRow(m)

        # add cells
        item = QTableWidgetItem(elem)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_ELEMENT, item)
        
        item = QTableWidgetItem(field)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_FIELD, item)

        
        item = QTableWidgetItem(', '.join(pvsrb))
        #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        self.table.setItem(m, self.COL_PV, item)

        readval = ['%.4e' % v for v in caget(pvsrb)]
        item = QTableWidgetItem(', '.join(readval))
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_READBACK, item)

        # set the stepsize of PV
        stepsize = 0.00001
        if pvssp:
            item = QTableWidgetItem('%f' % stepsize)
            item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(m, self.COL_STEPSIZE, item)

            self.spinbox.append(QDoubleSpinBox(self.table))
            self.spinbox[-1].setRange(-100, 100)
            #self.spinbox[-1].setValue(float(10.0))
            self.spinbox[-1].setSingleStep(stepsize)
            self.spinbox[-1].setDecimals(10)
            
            self.spinbox[-1].valueChanged.connect(self._writePv)
            
            self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1])

            sp = float(caget(pvssp)[0])
            #print "setpoint:", pvssp, sp, type(sp)
            self.spinbox[-1].setValue(-1e-5)
            #print "connected", self.spinbox[-1].value()
        else:
            item = self.table.item(m, self.COL_STEPSIZE)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            item = self.table.item(m, self.COL_SETPOINT)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.spinbox.append(None)

        self.table.resizeColumnsToContents()

        
    def addPv(self):
        self._appendRecord(str(self.inputBox.text()))
        self._updateMonitors()

    def minimalSizeHint(self):
        return QSize(800, 600)


    def _writePv(self, v):
        """
        """
        c = QObject.sender(self)
        i = self.spinbox.index(c)
        #print i, c.text(), "changed"

        #print self.pvs_sp[i], v
        caput(self.pvs_sp[i], v)

    def _updateMonitors(self):
        """
        prepare the PV list for camonitor
        """
        #print "Updating monitors"
        pvs = []
        self.pvs_rb_val = []
        for i in range(self.table.rowCount()):
            for j in range(len(self.pvs_rb[i])):
                self.pvs_rb_val.append([i, 0.0])
            pvs.extend(self.pvs_rb[i])
        
        for p in self.pvmoni: p.close()
        self.pvmoni = camonitor(pvs, self._updatePvValues)
        #print self.pvmoni
        #print pvs
        #print self.pvs_rb_val


    def _updatePvValues(self, val, idx):
        #print idx, val
        s = []
        for i, v in enumerate(self.pvs_rb_val):
            if v[0] == self.pvs_rb_val[idx][0]:
                s.append(self.FMT_READBACK % val)
        #print s
        item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK)
        item.setText(','.join(s))

    def closePvMonitors(self):
        #print "Closing PV Monitors"
        for p in self.pvmoni: p.close()

        pass

    def closeEvent(self, event):
        self.closePvMonitors()
        event.accept()

    def close(self):
        self.closePvMonitors()
        return True
Exemplo n.º 6
0
class MainWidget(QMainWindow):


    def __init__(self, parent=None):
        super(MainWidget, self).__init__(
                parent,
                windowTitle='GithubRemote',
                windowIcon=QIcon(image_path('git.png')),
                geometry=QRect(300, 300, 600, 372))

        self.repo_pixmap = QPixmap(image_path('book_16.png'))
        self.big_repo_pixmap = QPixmap(image_path('book_32.png'))
        self.repo_fork_pixmap = QPixmap(image_path('book_fork_16.png'))
        self.star_pixmap = QPixmap(image_path('star_16.png'))
        self.big_star_pixmap = QPixmap(image_path('star_32.png'))
        self.fork_pixmap = QPixmap(image_path('fork_16.png'))
        self.eye_pixmap = QPixmap(image_path('eye_16.png'))

        self.github = None        

        # Actions

        self.repoAddAction = QAction(
                QIcon(image_path('plus_48.png')),
                '&Add Repo', self,
                statusTip='Add a new repo')
        self.repoAddAction.triggered.connect(self.repoAdd)
        
        self.repoRemoveAction = QAction(
                QIcon(image_path('minus.png')),
                '&Remove Repo', self,
                statusTip='Remove repo')
        self.repoRemoveAction.triggered.connect(self.repoRemove)

        self.repoRefreshAction = QAction(
                QIcon(image_path('refresh.png')),
                'Refresh', self,
                statusTip='Refresh list of repos')
        self.repoRefreshAction.triggered.connect(self.reposRefresh)
        self.repoRefreshAction.triggered.connect(self.starsRefresh)

        self.addAccountAction = QAction(
                'Add Account', self,
                statusTip='Add Account')
        self.addAccountAction.triggered.connect(self.addAccount)

        # userPushButton - Displays the current active username and 
        # image on the top right of the toolbar.
        
        self.userButtonMenu = UserButtonMenu(32,32)

        # ToolBar

        self.toolBar = self.addToolBar('Main')
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolBar.addAction(self.repoAddAction)
        self.toolBar.addAction(self.repoRemoveAction)
        self.toolBar.addAction(self.repoRefreshAction)
        self.toolBar.addWidget(spacer)
        self.toolBar.addWidget(self.userButtonMenu)

        # Menu

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        actionMenu = menuBar.addMenu('&Action')
        fileMenu.addAction(self.addAccountAction)
        actionMenu.addAction(self.repoAddAction)
        actionMenu.addAction(self.repoRemoveAction)
        actionMenu.addAction(self.repoRefreshAction)

        # StatusBar

        statusBar = self.statusBar()
        self.setStatusBar(statusBar)

        # reposTableWidget - Displays a list of the users repositories

        self.reposTableWidget = QTableWidget(0, 5,
                selectionBehavior = QAbstractItemView.SelectRows,
                selectionMode = QAbstractItemView.SingleSelection,
                editTriggers = QAbstractItemView.NoEditTriggers,
                itemSelectionChanged = self.actionsUpdate)
        self.reposTableWidget.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.reposTableWidget.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.reposTableWidget.horizontalHeader().setVisible(False)
        self.reposTableWidget.verticalHeader().setVisible(False)
        self.reposTableWidget.setShowGrid(False)
        self.reposTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        reposTab = QWidget()
        reposTabLayout = QVBoxLayout(reposTab)
        reposTabLayout.addWidget(self.reposTableWidget)
        reposTab.setLayout(reposTabLayout)

        # starsTableWidget - Displays a list of the users repositories

        self.starsTableWidget = QTableWidget(0, 5,
                selectionBehavior = QAbstractItemView.SelectRows,
                selectionMode = QAbstractItemView.SingleSelection,
                editTriggers = QAbstractItemView.NoEditTriggers,
                itemSelectionChanged = self.actionsUpdate)
        self.starsTableWidget.horizontalHeader().setResizeMode(
                QHeaderView.ResizeToContents)
        self.starsTableWidget.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)
        self.starsTableWidget.horizontalHeader().setVisible(False)
        self.starsTableWidget.verticalHeader().setVisible(False)
        self.starsTableWidget.setShowGrid(False)
        self.starsTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        starsTab = QWidget()
        starsTabLayout = QVBoxLayout(starsTab)
        starsTabLayout.addWidget(self.starsTableWidget)
        starsTab.setLayout(starsTabLayout)
        
        # Tab Widget
        self.tabs = QTabWidget()
        self.tabs.setTabBar(FlippedTabBar(self))
        self.tabs.addTab(reposTab, QIcon(self.big_repo_pixmap), "repos")
        self.tabs.addTab(starsTab, QIcon(self.big_star_pixmap), "stars")
        self.tabs.setTabPosition(QTabWidget.West)

        # Layout

        self.setCentralWidget(self.tabs)
        self.actionsUpdate()
        self.show()
        
        # Update

        self.loadUserMenu()
        if self.activeUserAction:
            self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    
    @waiting_effects
    def updateImage(self):

        try:
            url = self.github.get_user().avatar_url
        except (GithubException, AttributeError): 
            return 
        data = urllib.urlopen(url).read()
        pixmap = QPixmap()
        pixmap.loadFromData(data)
        self.activeUserAction.setIcon(QIcon(pixmap))
        self.userButtonMenu.setPixmap(pixmap)
        self.userButtonMenu.setText(self.github.get_user().login)
   
    @waiting_effects
    def loadUserMenu(self):
        
        action = None
        for _, username, token in generate_tokens(CONFIG_PATH, 'github'):
            
            try:
                url = Github(token).get_user().avatar_url
            except (GithubException, AttributeError): 
                action = QAction(username, self, triggered=self.changeActive)
                self.userButtonMenu.addAction(action)
                continue
            data = urllib.urlopen(url).read()
            pixmap = QPixmap()
            pixmap.loadFromData(data)
            action = QAction(QIcon(pixmap), username, self,
                    triggered=self.changeActive)
            action.setIconVisibleInMenu(True)
            self.userButtonMenu.addAction(action)
        
        self.activeUserAction = action
    
    def changeActive(self):

        sender = self.sender()

        self.activeUserAction.setVisible(True)
        self.activeUserAction = sender
        self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def reposRefresh(self):

        self.reposTableWidget.clearContents()

        try:
            repos = self.github.get_user().get_repos()
            self.reposTableWidget.setRowCount(self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(repos):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.reposTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel('<b>{}</b><br />{}'.format(
                        str(repo.name), str(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.reposTableWidget.setCellWidget(row, 1, label)
            self.reposTableWidget.setItem(row, 2, 
                    QTableWidgetItem(QIcon(self.star_pixmap), str(repo.stargazers_count)))
            self.reposTableWidget.setItem(row, 3, 
                    QTableWidgetItem(QIcon(self.eye_pixmap), str(repo.watchers_count)))
            self.reposTableWidget.setItem(row, 4, 
                    QTableWidgetItem(QIcon(self.fork_pixmap), str(repo.forks_count)))

        self.reposTableWidget.resizeRowsToContents()

    @waiting_effects
    def starsRefresh(self):

        self.starsTableWidget.clearContents()

        try:
            starred = self.github.get_user().get_starred()
            self.starsTableWidget.setRowCount(self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(starred):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.starsTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel(u'<b>{}/{}</b><br />{}'.format(
                unicode(repo.owner.login), unicode(repo.name), unicode(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.starsTableWidget.setCellWidget(row, 1, label)
            self.starsTableWidget.setItem(row, 2, 
                    QTableWidgetItem(QIcon(self.star_pixmap), '0'))
            self.starsTableWidget.setItem(row, 3, 
                    QTableWidgetItem(QIcon(self.eye_pixmap), str(repo.watchers_count)))
            self.starsTableWidget.setItem(row, 4, 
                    QTableWidgetItem(QIcon(self.fork_pixmap), str(repo.forks_count)))

        self.starsTableWidget.resizeRowsToContents()

    @waiting_effects
    def authenticate(self):
        
        if self.activeUserAction:
            username = str(self.activeUserAction.text())
            token = load_token(CONFIG_PATH, 'github', username) 
            self.github = Github(token)
        else:
            self.github = None

    
    def actionsUpdate(self):
        # TODO disable if no user is logged in
        if self.github is None:
            self.repoAddAction.setEnabled(False)
            self.repoRemoveAction.setEnabled(False)
            self.repoRefreshAction.setEnabled(False)
        else:
            self.repoAddAction.setEnabled(True)
            self.repoRefreshAction.setEnabled(True)
            if self._isARepoSelected():
                self.repoRemoveAction.setEnabled(True)
            else:
                self.repoRemoveAction.setEnabled(False)

    def addAccount(self):
        wizard = AddAccountWizard(self)
        if wizard.exec_():
            username = str(wizard.field('username').toString())
            token = str(wizard.field('token').toString())
            store_token(CONFIG_PATH, 'github', username, token)
            self.authenticate()
            self.reposRefresh()
            self.updateImage()
            self.actionsUpdate()

    def repoAdd(self):
        wizard = AddRepoWizard(self.github, self)
        if wizard.exec_():
            self.github.get_user().create_repo(
                str(wizard.field('name').toString()),
                description=str(wizard.field('description').toString()),
                private=bool(wizard.field('private').toBool()),
                auto_init=bool(wizard.field('auto_init').toBool()),
                gitignore_template=str(wizard.field('gitignore').toString()),
                homepage=str(wizard.field('homepage').toString()),
                has_wiki=bool(wizard.field('has_wiki').toBool()),
                has_downloads=bool(wizard.field('has_downloads').toBool()),
                has_issues=bool(wizard.field('has_issues').toBool()))
            self.reposRefresh()
    
    def repoRemove(self):
        
        row = self._selectedRepoRow()
        name = self.reposTableWidget.item(row, 0).text()
        dialog = RepoRemoveDialog(self.github, name)
        if dialog.exec_():
            self.github.get_user().get_repo(str(name)).delete()
            self.reposRefresh()

    def _isARepoSelected(self):
        """ Return True if a repo is selected else False """
        if len(self.reposTableWidget.selectedItems()) > 0:
            return True
        else:
            return False

    def _selectedRepoRow(self):
        """ Return the currently select repo """
        # TODO - figure out what happens if no repo is selected
        selectedModelIndexes = \
            self.reposTableWidget.selectionModel().selectedRows()
        for index in selectedModelIndexes:
            return index.row()
Exemplo n.º 7
0
def make_widget(main, show=True):

    id = main.persistant['id']
    table = QTableWidget()
    table.controller = ROITableController(table, main)
    table.setGeometry(QRect(20, 33, 496, 296))
    table.setWindowTitle('ceilingfaan - ROI Table - Work in progress')
    analysis = s.query(Analysis).order_by(Analysis.date.desc()).all()
    table.setRowCount(len(analysis))
    table.setColumnCount(4)
    table.setHorizontalHeaderLabels(
        QString('CONTROL,DATE,MOUSE,FILENAME').split(','))

    current_analysis = None
    on_render = table.controller.on('render')
    on_import = table.controller.on('import')
    for nrow, entity in enumerate(analysis):
        if entity.id == id:
            print 'Found matching analysis data', id, 'at nrow:', nrow
            current_analysis = entity
            current_nrow = nrow
            continue

        for ncol, attr in enumerate('date mouse_id filename'.split()):
            field = getattr(entity, attr)
            item = QTableWidgetItem(str(field))
            item.setFlags(Qt.ItemIsEnabled)
            table.setItem(nrow, ncol + 1, item)

        render_btn = QPushButton('Render', checkable=True)
        render_btn.setStyleSheet('font-size: 9px; background-color: skyblue;')
        import_btn = QPushButton('Import')
        import_btn.setStyleSheet('font-size: 9px;')

        btn_layout = QHBoxLayout()
        btn_layout.setContentsMargins(5, 0, 5, 0)
        btn_layout.addWidget(render_btn)
        btn_layout.addWidget(import_btn)

        btn_widget = QWidget()
        btn_widget.nrow = nrow
        btn_widget.analysis_id = entity.id
        btn_widget.ext_roi_set = None
        btn_widget.setLayout(btn_layout)
        table.setCellWidget(nrow, 0, btn_widget)

        render_btn.clicked.connect(on_render)
        import_btn.clicked.connect(on_import)

    if current_analysis:
        table.removeRow(current_nrow)
        table.insertRow(0)
        item = QTableWidgetItem('Current Analysis')
        item.setFlags(Qt.ItemIsEnabled)
        item.setTextAlignment(Qt.AlignCenter)
        table.setItem(0, 0, item)
        for ncol, attr in enumerate('date mouse_id filename'.split()):
            field = getattr(current_analysis, attr)
            item = QTableWidgetItem(str(field))
            item.setFlags(Qt.ItemIsEnabled)
            table.setItem(0, ncol + 1, item)
        # debug.enter()

    table.setSelectionBehavior(QTableWidget.SelectRows)
    table.setSelectionMode(QTableWidget.NoSelection)
    table.resizeColumnsToContents()
    table.horizontalHeader().setStretchLastSection(True)

    if show: table.show()

    return table
Exemplo n.º 8
0
class MainWidget(QMainWindow):
    def __init__(self, parent=None):
        super(MainWidget,
              self).__init__(parent,
                             windowTitle='GithubRemote',
                             windowIcon=QIcon(image_path('git.png')),
                             geometry=QRect(300, 300, 600, 372))

        self.repo_pixmap = QPixmap(image_path('book_16.png'))
        self.big_repo_pixmap = QPixmap(image_path('book_32.png'))
        self.repo_fork_pixmap = QPixmap(image_path('book_fork_16.png'))
        self.star_pixmap = QPixmap(image_path('star_16.png'))
        self.big_star_pixmap = QPixmap(image_path('star_32.png'))
        self.fork_pixmap = QPixmap(image_path('fork_16.png'))
        self.eye_pixmap = QPixmap(image_path('eye_16.png'))

        self.github = None

        # Actions

        self.repoAddAction = QAction(QIcon(image_path('plus_48.png')),
                                     '&Add Repo',
                                     self,
                                     statusTip='Add a new repo')
        self.repoAddAction.triggered.connect(self.repoAdd)

        self.repoRemoveAction = QAction(QIcon(image_path('minus.png')),
                                        '&Remove Repo',
                                        self,
                                        statusTip='Remove repo')
        self.repoRemoveAction.triggered.connect(self.repoRemove)

        self.repoRefreshAction = QAction(QIcon(image_path('refresh.png')),
                                         'Refresh',
                                         self,
                                         statusTip='Refresh list of repos')
        self.repoRefreshAction.triggered.connect(self.reposRefresh)
        self.repoRefreshAction.triggered.connect(self.starsRefresh)

        self.addAccountAction = QAction('Add Account',
                                        self,
                                        statusTip='Add Account')
        self.addAccountAction.triggered.connect(self.addAccount)

        # userPushButton - Displays the current active username and
        # image on the top right of the toolbar.

        self.userButtonMenu = UserButtonMenu(32, 32)

        # ToolBar

        self.toolBar = self.addToolBar('Main')
        self.toolBar.setMovable(False)
        self.toolBar.setFloatable(False)
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.toolBar.addAction(self.repoAddAction)
        self.toolBar.addAction(self.repoRemoveAction)
        self.toolBar.addAction(self.repoRefreshAction)
        self.toolBar.addWidget(spacer)
        self.toolBar.addWidget(self.userButtonMenu)

        # Menu

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        actionMenu = menuBar.addMenu('&Action')
        fileMenu.addAction(self.addAccountAction)
        actionMenu.addAction(self.repoAddAction)
        actionMenu.addAction(self.repoRemoveAction)
        actionMenu.addAction(self.repoRefreshAction)

        # StatusBar

        statusBar = self.statusBar()
        self.setStatusBar(statusBar)

        # reposTableWidget - Displays a list of the users repositories

        self.reposTableWidget = QTableWidget(
            0,
            5,
            selectionBehavior=QAbstractItemView.SelectRows,
            selectionMode=QAbstractItemView.SingleSelection,
            editTriggers=QAbstractItemView.NoEditTriggers,
            itemSelectionChanged=self.actionsUpdate)
        self.reposTableWidget.horizontalHeader().setResizeMode(
            QHeaderView.ResizeToContents)
        self.reposTableWidget.horizontalHeader().setResizeMode(
            1, QHeaderView.Stretch)
        self.reposTableWidget.horizontalHeader().setVisible(False)
        self.reposTableWidget.verticalHeader().setVisible(False)
        self.reposTableWidget.setShowGrid(False)
        self.reposTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        reposTab = QWidget()
        reposTabLayout = QVBoxLayout(reposTab)
        reposTabLayout.addWidget(self.reposTableWidget)
        reposTab.setLayout(reposTabLayout)

        # starsTableWidget - Displays a list of the users repositories

        self.starsTableWidget = QTableWidget(
            0,
            5,
            selectionBehavior=QAbstractItemView.SelectRows,
            selectionMode=QAbstractItemView.SingleSelection,
            editTriggers=QAbstractItemView.NoEditTriggers,
            itemSelectionChanged=self.actionsUpdate)
        self.starsTableWidget.horizontalHeader().setResizeMode(
            QHeaderView.ResizeToContents)
        self.starsTableWidget.horizontalHeader().setResizeMode(
            1, QHeaderView.Stretch)
        self.starsTableWidget.horizontalHeader().setVisible(False)
        self.starsTableWidget.verticalHeader().setVisible(False)
        self.starsTableWidget.setShowGrid(False)
        self.starsTableWidget.verticalHeader().setMinimumSectionSize(25)

        # repoTab - Layout
        starsTab = QWidget()
        starsTabLayout = QVBoxLayout(starsTab)
        starsTabLayout.addWidget(self.starsTableWidget)
        starsTab.setLayout(starsTabLayout)

        # Tab Widget
        self.tabs = QTabWidget()
        self.tabs.setTabBar(FlippedTabBar(self))
        self.tabs.addTab(reposTab, QIcon(self.big_repo_pixmap), "repos")
        self.tabs.addTab(starsTab, QIcon(self.big_star_pixmap), "stars")
        self.tabs.setTabPosition(QTabWidget.West)

        # Layout

        self.setCentralWidget(self.tabs)
        self.actionsUpdate()
        self.show()

        # Update

        self.loadUserMenu()
        if self.activeUserAction:
            self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def updateImage(self):

        try:
            url = self.github.get_user().avatar_url
        except (GithubException, AttributeError):
            return
        data = urllib.urlopen(url).read()
        pixmap = QPixmap()
        pixmap.loadFromData(data)
        self.activeUserAction.setIcon(QIcon(pixmap))
        self.userButtonMenu.setPixmap(pixmap)
        self.userButtonMenu.setText(self.github.get_user().login)

    @waiting_effects
    def loadUserMenu(self):

        action = None
        for _, username, token in generate_tokens(CONFIG_PATH, 'github'):

            try:
                url = Github(token).get_user().avatar_url
            except (GithubException, AttributeError):
                action = QAction(username, self, triggered=self.changeActive)
                self.userButtonMenu.addAction(action)
                continue
            data = urllib.urlopen(url).read()
            pixmap = QPixmap()
            pixmap.loadFromData(data)
            action = QAction(QIcon(pixmap),
                             username,
                             self,
                             triggered=self.changeActive)
            action.setIconVisibleInMenu(True)
            self.userButtonMenu.addAction(action)

        self.activeUserAction = action

    def changeActive(self):

        sender = self.sender()

        self.activeUserAction.setVisible(True)
        self.activeUserAction = sender
        self.activeUserAction.setVisible(False)
        self.authenticate()
        self.actionsUpdate()
        self.reposRefresh()
        self.starsRefresh()
        self.updateImage()

    @waiting_effects
    def reposRefresh(self):

        self.reposTableWidget.clearContents()

        try:
            repos = self.github.get_user().get_repos()
            self.reposTableWidget.setRowCount(
                self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(repos):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.reposTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel('<b>{}</b><br />{}'.format(str(repo.name),
                                                      str(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.reposTableWidget.setCellWidget(row, 1, label)
            self.reposTableWidget.setItem(
                row, 2,
                QTableWidgetItem(QIcon(self.star_pixmap),
                                 str(repo.stargazers_count)))
            self.reposTableWidget.setItem(
                row, 3,
                QTableWidgetItem(QIcon(self.eye_pixmap),
                                 str(repo.watchers_count)))
            self.reposTableWidget.setItem(
                row, 4,
                QTableWidgetItem(QIcon(self.fork_pixmap),
                                 str(repo.forks_count)))

        self.reposTableWidget.resizeRowsToContents()

    @waiting_effects
    def starsRefresh(self):

        self.starsTableWidget.clearContents()

        try:
            starred = self.github.get_user().get_starred()
            self.starsTableWidget.setRowCount(
                self.github.get_user().public_repos)
        except (GithubException, AttributeError):
            return
        for row, repo in enumerate(starred):
            imageLabel = QLabel()
            if repo.fork:
                imageLabel.setPixmap(self.repo_fork_pixmap)
            else:
                imageLabel.setPixmap(self.repo_pixmap)
            imageLabel.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            imageLabel.setMargin(5)

            self.starsTableWidget.setCellWidget(row, 0, imageLabel)
            label = QLabel(u'<b>{}/{}</b><br />{}'.format(
                unicode(repo.owner.login), unicode(repo.name),
                unicode(repo.description)))
            label.setAlignment(Qt.AlignVCenter)
            label.setMargin(5)
            label.setWordWrap(True)
            self.starsTableWidget.setCellWidget(row, 1, label)
            self.starsTableWidget.setItem(
                row, 2, QTableWidgetItem(QIcon(self.star_pixmap), '0'))
            self.starsTableWidget.setItem(
                row, 3,
                QTableWidgetItem(QIcon(self.eye_pixmap),
                                 str(repo.watchers_count)))
            self.starsTableWidget.setItem(
                row, 4,
                QTableWidgetItem(QIcon(self.fork_pixmap),
                                 str(repo.forks_count)))

        self.starsTableWidget.resizeRowsToContents()

    @waiting_effects
    def authenticate(self):

        if self.activeUserAction:
            username = str(self.activeUserAction.text())
            token = load_token(CONFIG_PATH, 'github', username)
            self.github = Github(token)
        else:
            self.github = None

    def actionsUpdate(self):
        # TODO disable if no user is logged in
        if self.github is None:
            self.repoAddAction.setEnabled(False)
            self.repoRemoveAction.setEnabled(False)
            self.repoRefreshAction.setEnabled(False)
        else:
            self.repoAddAction.setEnabled(True)
            self.repoRefreshAction.setEnabled(True)
            if self._isARepoSelected():
                self.repoRemoveAction.setEnabled(True)
            else:
                self.repoRemoveAction.setEnabled(False)

    def addAccount(self):
        wizard = AddAccountWizard(self)
        if wizard.exec_():
            username = str(wizard.field('username').toString())
            token = str(wizard.field('token').toString())
            store_token(CONFIG_PATH, 'github', username, token)
            self.authenticate()
            self.reposRefresh()
            self.updateImage()
            self.actionsUpdate()

    def repoAdd(self):
        wizard = AddRepoWizard(self.github, self)
        if wizard.exec_():
            self.github.get_user().create_repo(
                str(wizard.field('name').toString()),
                description=str(wizard.field('description').toString()),
                private=bool(wizard.field('private').toBool()),
                auto_init=bool(wizard.field('auto_init').toBool()),
                gitignore_template=str(wizard.field('gitignore').toString()),
                homepage=str(wizard.field('homepage').toString()),
                has_wiki=bool(wizard.field('has_wiki').toBool()),
                has_downloads=bool(wizard.field('has_downloads').toBool()),
                has_issues=bool(wizard.field('has_issues').toBool()))
            self.reposRefresh()

    def repoRemove(self):

        row = self._selectedRepoRow()
        name = self.reposTableWidget.item(row, 0).text()
        dialog = RepoRemoveDialog(self.github, name)
        if dialog.exec_():
            self.github.get_user().get_repo(str(name)).delete()
            self.reposRefresh()

    def _isARepoSelected(self):
        """ Return True if a repo is selected else False """
        if len(self.reposTableWidget.selectedItems()) > 0:
            return True
        else:
            return False

    def _selectedRepoRow(self):
        """ Return the currently select repo """
        # TODO - figure out what happens if no repo is selected
        selectedModelIndexes = \
            self.reposTableWidget.selectionModel().selectedRows()
        for index in selectedModelIndexes:
            return index.row()
Exemplo n.º 9
0
class K800IRec(QWidget, mfso):
    def __init__(self):
        mfso.__init__(self, "K800i-Recover")
        self.name = "K800i-Recover"
        self.icon = None
        self.__disown__()

    def start(self, args):
        self.vfs = vfs.vfs()
        self.dumpnumber = 1
        try:
            self.nor = args['nor'].value()
            self.nand = args['nand'].value()
        except IndexError:
            return
        try:
            self.spareSize = args["spare-size"].value()
        except IndexError:
            self.spareSize = 16
        try:
            self.pageSize = args["page-size"].value()
        except IndexError:
            self.pageSize = 512
        self.k800n = Node("k800-base")
        self.k800n.__disown__()
        self.boot = SEBootBlock(self.nor, self.pageSize)
        self.blockSize = self.boot.blockSize
        self.nandClean = SpareNode(self, self.nand, "nandfs", self.pageSize,
                                   self.spareSize, self.k800n)
        self.norFs = NorFs(self, self.k800n, self.nor, "norfs", self.boot)
        self.fullFs = FullFs(self, self.k800n, self.norFs, self.nandClean,
                             "fullfs", self.boot)
        self.gdfs = GDFS(self, self.k800n, self.nor, "gdfs", self.boot)
        self.firmware = Firmware(self, self.k800n, self.nor, "firmware",
                                 self.boot.norfsoffset)

        self.tables = Tables(self.fullFs, self.blockSize)
        self.registerTree(self.nand, self.k800n)

    def createDump(self):
        text, ok = QInputDialog.getText(self, "Create dump", "dump name:",
                                        QLineEdit.Normal,
                                        "k800-restore-" + str(self.dumpnumber))
        if ok and text != "":
            if (self.vfs.getnode(self.nand.absolute() + "/" +
                                 str(text)) == None):
                self.dumpnumber += 1
                newroot = Node(str(text))
                newroot.__disown__()
                for id in range(0, len(self.tables.tablesIdWriteMap) - 1):
                    write = int(
                        str(self.gtable.cellWidget(id, 0).currentText()), 16)
                    self.tables.map[id] = self.tables.tablesIdWriteMap[id][
                        write]
                virtual = VirtualMap(self, newroot, self.fullFs, self.tables,
                                     "virtual", self.blockSize)
                separt = SEPartitionBlock(virtual, self.boot.partitionblock,
                                          self.blockSize)
                self.createPart(separt, newroot, virtual)
                self.registerTree(self.nand, newroot)
            else:
                box = QMessageBox(QMessageBox.Warning, "Error",
                                  "Error node already exists",
                                  QMessageBox.NoButton, self)
                box.exec_()
                self.createDump()

    def createPart(self, separt, newroot, virtual):
        for part in separt.partTable:
            if part.start > 0:
                p = Partition(self, newroot, virtual, part, self.blockSize)

    def g_display(self):
        QWidget.__init__(self, None)
        self.layout = QVBoxLayout(self)
        self.hlayout = QSplitter(self)
        self.layout.insertWidget(0, self.hlayout)
        self.layout.setStretchFactor(self.hlayout, 1)
        self.gTable()
        self.viewTable()

        self.button = QPushButton("&Create dump")
        self.connect(self.button, SIGNAL("clicked()"), self.createDump)
        self.layout.addWidget(self.button)

    def viewTable(self):
        self.vtable = QTableWidget()
        self.vtable.setColumnCount(20)
        self.vtable.setRowCount(48)
        self.hlayout.addWidget(self.vtable)

    def viewTableUpdate(self, id):
        write = int(str(self.gtable.cellWidget(id, 0).currentText()), 16)
        t = self.tables.tablesIdWriteMap[id][write]
        l = t.blockList
        for x in xrange(0, len(t.blockList[0])):
            block = t.blockList[0][x]
            c = ((x) % 20)
            r = ((x) / 20)
            item = QTableWidgetItem(QString(hex(block)))
            tipBlock = (id * 960) + x
            item.setToolTip(QString(hex(tipBlock)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.vtable.setItem(r, c, item)

    def gTable(self):
        self.gtable = QTableWidget()
        self.gtable.setColumnCount(1)
        self.gtable.setRowCount(len(self.tables.tablesIdWriteMap))
        self.gtable.setHorizontalHeaderItem(
            0, QTableWidgetItem(QString("version")))
        self.hlayout.addWidget(self.gtable)
        self.sigMapper = QSignalMapper(self)
        for id in self.tables.tablesIdWriteMap:
            wlist = self.tables.tablesIdWriteMap[id]
            cbox = QComboBox(self.gtable)
            self.connect(cbox, SIGNAL("activated(QString)"), self.sigMapper,
                         SLOT("map()"))
            self.sigMapper.setMapping(cbox, id)
            l = []
            for write in wlist:
                l.append(write)
            l.sort()
            l.reverse()
            for write in l:
                cbox.addItem(QString(hex(write)))
            self.gtable.setCellWidget(id, 0, cbox)
            self.gtable.setVerticalHeaderItem(
                id, QTableWidgetItem(QString(hex(id))))
        self.connect(self.sigMapper, SIGNAL("mapped(int)"),
                     self.viewTableUpdate)
        self.gtable.setMaximumWidth(
            self.gtable.columnWidth(0) +
            self.gtable.verticalHeader().sectionSize(0) + 30)

    def updateWidget(self):
        pass
Exemplo n.º 10
0
class daq_window(QMainWindow):
    """Window to control and visualise DAQ measurements.
    Set up the desired channels with a given sampling rate.
    Start an acquisition after a trigger. 
    Display the acquired data on a trace, and accumulated
    data on a graph.
    
    Arguments:
    n       -- run number for synchronisation
    rate    -- max sample rate in samples / second
    dt      -- desired acquisition period in seconds
    config_file -- path to file storing default settings
    port    -- the port number to open for TCP connections
    """
    def __init__(self, n=0, rate=250, dt=500, config_file='monitor\\daqconfig.dat', port=8622):
        super().__init__()
        self.types = OrderedDict([('n', int), ('config_file', str), ('trace_file', str), ('graph_file', str),
            ('save_dir', str), ('Sample Rate (kS/s)',float), 
            ('Duration (ms)', float), ('Trigger Channel', str), ('Trigger Level (V)', float), 
            ('Trigger Edge', str), ('channels',channel_stats)])
        self.stats = OrderedDict([('n', n), ('config_file', config_file), ('trace_file', 'DAQtrace.csv'), 
            ('graph_file', 'DAQgraph.csv'),('save_dir', '.'), ('Sample Rate (kS/s)', rate), 
            ('Duration (ms)', dt), ('Trigger Channel', 'Dev2/ai1'), # /Dev2/PFI0
            ('Trigger Level (V)', 1.0), ('Trigger Edge', 'rising'), 
            ('channels', channel_stats("[['Dev2/ai0', '0', '1.0', '0.0', '5', '1', '1']]"))])
        self.trigger_toggle = True       # whether to trigger acquisition or just take a measurement
        self.slave = worker(rate*1e3, dt/1e3, self.stats['Trigger Channel'], 
                self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), 
                [ch['range'] for ch in self.stats['channels'].values()]) # this controls the DAQ
        self.dc = daqCollection(param=[], channels=list(self.stats['channels'].keys()))
        self.init_UI()
        self.load_config(config_file)    # load default settings          
        self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)']) # number of samples per acquisition
        self.last_path = './'

        self.x = [] # run numbers for graphing collections of acquired data
        self.y = [] # average voltages in slice of acquired trace 

        self.slave.acquired.connect(self.update_graph) # take average of slices
        self.slave.acquired.connect(self.update_trace) # plot new data when it arrives
        self.tcp = PyClient(port=port)
        remove_slot(self.tcp.dxnum, self.set_n, True)
        remove_slot(self.tcp.textin, self.respond, True)
        self.tcp.start()

    def init_UI(self):
        """Produce the widgets and buttons."""
        self.centre_widget = QWidget()
        self.tabs = QTabWidget()       # make tabs for each main display 
        self.centre_widget.layout = QVBoxLayout()
        self.centre_widget.layout.addWidget(self.tabs)
        self.centre_widget.setLayout(self.centre_widget.layout)
        self.setCentralWidget(self.centre_widget)
        
        # change font size
        font = QFont()
        font.setPixelSize(18)

        #### menubar at top gives options ####
        menubar = self.menuBar()

        # file menubar allows you to save/load data
        file_menu = menubar.addMenu('File')
        for label, function in [['Load Config', self.load_config],
                ['Save Config', self.save_config],
                ['Load Trace', self.load_trace], 
                ['Save Trace', self.save_trace], 
                ['Save Graph', self.save_graph]]:
            action = QAction(label, self) 
            action.triggered.connect(function)
            file_menu.addAction(action)

        #### tab for settings  ####
        settings_tab = QWidget()
        settings_grid = QGridLayout()
        settings_tab.setLayout(settings_grid)
        self.tabs.addTab(settings_tab, "Settings")

        self.settings = QTableWidget(1, 6)
        self.settings.setHorizontalHeaderLabels(['Duration (ms)', 
            'Sample Rate (kS/s)', 'Trigger Channel', 'Trigger Level (V)', 
            'Trigger Edge', 'Use Trigger?'])
        settings_grid.addWidget(self.settings, 0,0, 1,1)
        defaults = [str(self.stats['Duration (ms)']), str(self.stats['Sample Rate (kS/s)']), 
            self.stats['Trigger Channel'], str(self.stats['Trigger Level (V)']), 
            self.stats['Trigger Edge'], '1']
        validators = [double_validator, double_validator, None, double_validator, None, bool_validator]
        for i in range(6):
            table_item = QLineEdit(defaults[i]) # user can edit text to change the setting
            if defaults[i] == 'Sample Rate (kS/s)': table_item.setEnabled(False)
            table_item.setValidator(validators[i]) # validator limits the values that can be entered
            self.settings.setCellWidget(0,i, table_item)
        self.settings.resizeColumnToContents(1) 
        self.settings.setFixedHeight(70) # make it take up less space
        self.settings.cellWidget(0,0).textChanged.connect(self.check_slice_duration)
                    
        # start/stop: start waiting for a trigger or taking an acquisition
        self.toggle = QPushButton('Start', self)
        self.toggle.setCheckable(True)
        self.toggle.clicked.connect(self.activate)
        settings_grid.addWidget(self.toggle, 1,0, 1,1)

        # channels
        self.channels = QTableWidget(8, 7) # make table
        self.channels.setHorizontalHeaderLabels(['Channel', 'Label', 
            'Scale (X/V)', 'Offset (V)', 'Range', 'Acquire?', 'Plot?'])
        settings_grid.addWidget(self.channels, 2,0, 1,1) 
        validators = [None, double_validator, double_validator, None, bool_validator, bool_validator]
        for i in range(8):
            chan = 'Dev2/ai'+str(i)  # name of virtual channel
            table_item = QLabel(chan)
            self.channels.setCellWidget(i,0, table_item)
            if chan in self.stats['channels']: # load values from previous
                defaults = self.stats['channels'][chan]
            else: # default values when none are loaded
                defaults = channel_stats("[dummy, "+str(i)+", 1.0, 0.0, 5.0, 0, 0]")['dummy']
            for j, key in zip([0,1,2,4,5], ['label', 'scale', 'offset', 'acquire', 'plot']):
                table_item = QLineEdit(str(defaults[key]))
                if 'acquire' in key:
                    table_item.textChanged.connect(self.check_slice_channels)
                elif 'plot' in key:
                    table_item.textChanged.connect(self.set_acquire)
                table_item.setValidator(validators[j])        
                self.channels.setCellWidget(i,j+1, table_item)
            vrange = QComboBox() # only allow certain values for voltage range
            vrange.text = vrange.currentText # overload function so it's same as QLabel
            vrange.addItems(['%.1f'%x for x in self.slave.vrs])
            try: vrange.setCurrentIndex(self.slave.vrs.index(defaults['range']))
            except Exception as e: logger.error('Invalid channel voltage range\n'+str(e))
            self.channels.setCellWidget(i,4, vrange)

        #### Plot for most recently acquired trace ####
        trace_tab = QWidget()
        trace_grid = QGridLayout()
        trace_tab.setLayout(trace_grid)
        self.tabs.addTab(trace_tab, "Trace")
        
        # button activates horizontal line
        self.hline_toggle = QPushButton('Horizontal line', self, checkable=True)
        self.hline_toggle.clicked.connect(self.add_horizontal)
        trace_grid.addWidget(self.hline_toggle, 0,0, 1,1)
        self.hline_label = QLabel()
        trace_grid.addWidget(self.hline_label, 0,1, 1,1)
        fadeline_button = QPushButton('Persist', self)
        fadeline_button.clicked.connect(self.set_fadelines)
        trace_grid.addWidget(fadeline_button, 0,2, 1,1)
        

        # plot the trace
        self.trace_canvas = pg.PlotWidget()
        self.trace_legend = self.trace_canvas.addLegend()
        self.trace_canvas.getAxis('bottom').tickFont = font
        self.trace_canvas.getAxis('left').tickFont = font
        self.trace_canvas.setLabel('bottom', 'Time', 's', **{'font-size':'18pt'})
        self.trace_canvas.setLabel('left', 'Voltage', 'V', **{'font-size':'18pt'})
        self.lines = [] # handles for lines plotting the last measurement
        self.fadelines = [] # handles for previous measurement lines
        for i in range(8):
            chan = self.channels.cellWidget(i,1).text()
            self.lines.append(self.trace_canvas.plot([1], name=chan, 
                    pen=pg.mkPen(pg.intColor(i), width=3)))
            self.lines[i].hide()
            self.fadelines.append(self.trace_canvas.plot([1], 
                    pen=pg.mkPen(pg.intColor(i, alpha=50), width=2)))
            self.fadelines[i].hide()
        self.hline = pg.InfiniteLine(1., angle=0, pen='k', movable=True)
        self.trace_canvas.addItem(self.hline)
        self.hline.sigPositionChanged.connect(self.update_hline)
        self.hline.hide()
        
            
        trace_grid.addWidget(self.trace_canvas, 1,0, 1,3)
        
        #### Settings for slices of the trace accumulating into the graph ####
        slice_tab = QWidget()
        slice_grid = QGridLayout()
        slice_tab.setLayout(slice_grid)
        self.tabs.addTab(slice_tab, "Slice")
        
        # Buttons to add/remove slices and reset graph
        for i, (label, func) in enumerate([['Add slice', self.add_slice],
                ['Remove slice', self.del_slice], ['Reset graph', self.reset_graph]]):
            button = QPushButton(label, self)
            button.clicked.connect(func)
            slice_grid.addWidget(button, 0,i, 1,1)
        
        # parameters for slices
        self.slices = QTableWidget(0, 4) # make table
        self.slices.setHorizontalHeaderLabels(['Slice name', 
            'Start (ms)', 'End (ms)', 'Channels'])
        slice_grid.addWidget(self.slices, 1,0, 1,3) 

        #### Plot for graph of accumulated data ####
        graph_tab = QWidget()
        graph_grid = QGridLayout()
        graph_tab.setLayout(graph_grid)
        self.tabs.addTab(graph_tab, "Graph")

        self.mean_graph = pg.PlotWidget() # for plotting means
        self.stdv_graph = pg.PlotWidget() # for plotting standard deviations
        self.graph_legends = []
        for i, g in enumerate([self.mean_graph, self.stdv_graph]):
            g.getAxis('bottom').tickFont = font
            g.getAxis('bottom').setFont(font)
            g.getAxis('left').tickFont = font
            g.getAxis('left').setFont(font)
            graph_grid.addWidget(g, i,0, 1,1)
        self.reset_lines() # make a line for every slice channel
        self.stdv_graph.setLabel('bottom', 'Shot', '', **{'font-size':'18pt'})
        self.stdv_graph.setLabel('left', 'Standard Deviation', 'V', **{'font-size':'18pt'})
        self.mean_graph.setLabel('left', 'Mean', 'V', **{'font-size':'18pt'})
        
        #### tab for TCP message settings  ####
        tcp_tab = QWidget()
        tcp_grid = QGridLayout()
        tcp_tab.setLayout(tcp_grid)
        self.tabs.addTab(tcp_tab, "Sync")

        label = QLabel('Run number: ')
        tcp_grid.addWidget(label, 0,0, 1,1)
        self.n_edit = QLineEdit(str(self.stats['n']))
        self.n_edit.setValidator(int_validator)
        self.n_edit.textEdited[str].connect(self.set_n)
        tcp_grid.addWidget(self.n_edit, 0,1, 1,1)
        
        label = QLabel('Save directory: ')
        tcp_grid.addWidget(label, 1,0, 1,1)
        self.save_edit = QLineEdit(self.stats['save_dir'])
        self.save_edit.textEdited[str].connect(self.set_save_dir)
        tcp_grid.addWidget(self.save_edit, 1,1, 1,1)
        
        label = QLabel('Trace file name: ')
        tcp_grid.addWidget(label, 2,0, 1,1)
        self.trace_edit = QLineEdit(self.stats['trace_file'])
        self.trace_edit.textEdited[str].connect(self.set_trace_file)
        tcp_grid.addWidget(self.trace_edit, 2,1, 1,1)
        
        label = QLabel('Graph file name: ')
        tcp_grid.addWidget(label, 3,0, 1,1)
        self.graph_edit = QLineEdit(self.stats['graph_file'])
        self.graph_edit.textEdited[str].connect(self.set_graph_file)
        tcp_grid.addWidget(self.graph_edit, 3,1, 1,1)
        
        reset = QPushButton('Reset TCP client', self)
        reset.clicked.connect(self.reset_client)
        tcp_grid.addWidget(reset, 4,0, 1,1)

        #### Title and icon ####
        self.setWindowTitle('- NI DAQ Controller -')
        self.setWindowIcon(QIcon('docs/daqicon.png'))
        self.setGeometry(200, 200, 800, 600)

    #### user input functions ####

    def set_acquire(self):
        """If the user chooses to plot, set the same channel to acquire."""
        for i in range(self.channels.rowCount()):
            if BOOL(self.channels.cellWidget(i,6).text()): # plot
                self.channels.cellWidget(i,5).setText('1') # only plot if acquiring
    
    def check_settings(self):
        """Coerce the settings into allowed values."""
        statstr = "[[" # dictionary of channel names and properties
        for i in range(self.channels.rowCount()):
            self.trace_legend.items[i][1].setText(self.channels.cellWidget(i,1).text()) # label
            if BOOL(self.channels.cellWidget(i,5).text()): # acquire
                statstr += ', '.join([self.channels.cellWidget(i,j).text() 
                    for j in range(self.channels.columnCount())]) + '],['
        self.stats['channels'] = channel_stats(statstr[:-2] + ']')
        self.dc.channels = self.stats['channels'].keys()

        # acquisition settings
        self.stats['Duration (ms)'] = float(self.settings.cellWidget(0,0).text())
        # check that the requested rate is valid
        rate = float(self.settings.cellWidget(0,1).text())
        if len(self.stats['channels']) > 1 and rate > 245 / len(self.stats['channels']):
            rate = 245 / len(self.stats['channels'])
        elif len(self.stats['channels']) < 2 and rate > 250:
            rate = 250
        self.stats['Sample Rate (kS/s)'] = rate
        self.settings.cellWidget(0,1).setText('%.2f'%(rate))
        self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)'])
        # check the trigger channel is valid
        trig_chan = self.settings.cellWidget(0,2).text() 
        if 'Dev2/PFI' in trig_chan or 'Dev2/ai' in trig_chan:
            self.stats['Trigger Channel'] = trig_chan
        else: 
            self.stats['Trigger Channel'] = 'Dev2/ai0'
        self.settings.cellWidget(0,2).setText(str(self.stats['Trigger Channel']))
        self.stats['Trigger Level (V)'] = float(self.settings.cellWidget(0,3).text())
        self.stats['Trigger Edge'] = self.settings.cellWidget(0,4).text()
        self.trigger_toggle = BOOL(self.settings.cellWidget(0,5).text())
        
        
    def set_table(self):
        """Display the acquisition and channel settings in the table."""
        x = self.stats.copy() # prevent it getting overwritten
        for i in range(5):
            self.settings.cellWidget(0,i).setText(str(x[
                self.settings.horizontalHeaderItem(i).text()]))
        for i in range(8):
            ch = self.channels.cellWidget(i,0).text()
            if ch in x['channels']:
                for j, key in zip([0,1,2,4,5], 
                        ['label', 'scale', 'offset', 'acquire', 'plot']):
                    self.channels.cellWidget(i,j+1).setText(str(x['channels'][ch][key]))
                self.channels.cellWidget(i,4).setCurrentText('%.1f'%x['channels'][ch]['range'])
            else:
                self.channels.cellWidget(i,5).setText('0') # don't acquire
                self.channels.cellWidget(i,6).setText('0') # don't plot

    #### slice settings functions ####

    def add_slice(self, param=[]):
        """Add a row to the slice table and append it to the
        daqCollection instance for analysis.
        param -- [name, start (ms), end (ms), channels]"""
        try:
            name, start, end, channels = param
        except TypeError:
            name = 'Slice' + str(self.slices.rowCount())
            start = 0
            end = self.stats['Duration (ms)']
            channels = list(self.stats['channels'].keys())
        i = self.slices.rowCount() # index to add row at
        self.slices.insertRow(i) # add row to table
        validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3)
        for j, text in enumerate([name, str(start), str(end)]):
            item = QLineEdit(text)
            item.pos = (i, j)
            if j > 0:
                item.setValidator(validator)
            item.textChanged.connect(self.update_slices)
            self.slices.setCellWidget(i, j, item)
        chanbox = QListWidget(self)
        chanbox.setSelectionMode(3) # extended selection, allows multiple selection
        chanbox.itemSelectionChanged.connect(self.update_slices)
        chanbox.pos = (i, 3)
        chanbox.text = chanbox.objectName
        chanlist = list(self.stats['channels'].keys())
        chanbox.addItems(chanlist)
        self.slices.setCellWidget(i, j+1, chanbox)
        self.slices.resizeRowToContents(i) 
        # add to the dc list of slices
        t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples)
        self.dc.add_slice(name, np.argmin(np.abs(t-start)), np.argmin(np.abs(t-end)), 
            OrderedDict([(chan, chanlist.index(chan)) for chan in channels]))
            
        self.reset_lines()
            

    def del_slice(self, toggle=True):
        """Remove the slice at the selected row of the slice table."""
        index = self.slices.currentRow()
        self.slices.removeRow(index)
        if index >= 0:
            self.dc.slices.pop(index)
        
    def check_slice_duration(self, newtxt):
        """If the acquisition duration is changed, make sure the slices can't
        use times beyond this."""
        self.check_settings() # update DAQ acquisition settings first
        for i in range(self.slices.rowCount()):
            for j in [1,2]: # force slice to be within max duration
                validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3)
                self.slices.cellWidget(i, j).setValidator(validator)

    def check_slice_channels(self, newtxt):
        """If the channels that can be used for the acquisition are changed, 
        change the list widgets in the slice settings to match."""
        self.check_settings() # update DAQ acquisition settings first
        for i in range(self.slices.rowCount()):
            w = self.slices.cellWidget(i, 3) # widget shorthand
            selected = [w.row(x) for x in w.selectedItems()] # make record of selected channels
            w.clear()
            w.addItems(list(self.stats['channels'].keys()))
            for r in selected:
                try:
                    w.setCurrentRow(r, QItemSelectionModel.SelectCurrent)
                except Exception as e: pass

    def update_slices(self, newtxt=''):
        """Use the current item from the table to update the parameter for the slices."""
        try:
            w = self.sender()
            i, j = w.pos
            t = np.linspace(0, self.stats['Duration (ms)'], self.n_samples)
            x = self.dc.slices[i] # shorthand
            if j == 0: # name
                x.name = w.text()
            elif j == 1: # start (ms)
                x.i0 = np.argmin(np.abs(t-float(w.text())))
            elif j == 2: # end (ms)
                x.i1 = np.argmin(np.abs(t-float(w.text())))
            elif j == 3:
                x.channels = OrderedDict([(x.text(), w.row(x)) for x in w.selectedItems()])
                x.stats = OrderedDict([(chan, OrderedDict([
                    ('mean',[]), ('stdv',[])])) for chan in x.channels.keys()])
                self.reset_lines()
                self.reset_graph()
            x.inds = slice(x.i0, x.i1+1)
            x.size = x.i1 - x.i0
        except IndexError as e: pass # logger.error("Couldn't update slice.\n"+str(e))    

    #### TCP functions ####
    
    def set_n(self, num):
        """Receive the new run number to update to"""
        self.stats['n'] = int(num)
        self.n_edit.setText(str(num))
        
    def set_save_dir(self, directory):
        """Set the directory to save results to"""
        self.stats['save_dir'] = directory
        self.save_edit.setText(directory)
        
    def set_trace_file(self, fname):
        """Set the default name for trace files when they're saved."""
        self.stats['trace_file'] = fname
        self.trace_edit.setText(fname)
    
    def set_graph_file(self, fname):
        """Set the default name for graph files when they're saved."""
        self.stats['graph_file'] = fname
        self.graph_edit.setText(fname)
        
    def reset_client(self, toggle=True):
        """Stop the TCP client thread then restart it."""
        self.tcp.stop = True
        for i in range(100): # wait til it's stopped
            if not self.tcp.isRunning():
                break
            else: time.sleep(0.001)
        self.tcp.start() # restart
        
    def respond(self, msg=''):
        """Interpret a TCP message. For setting properties, the syntax is:
        value=property. E.g. 'Z:\Tweezer=save_dir'."""
        if 'save_dir' in msg: 
            self.set_save_dir(msg.split('=')[0])
        elif 'trace_file' in msg:
            self.set_trace_file(msg.split('=')[0])
        elif 'graph_file' in msg:
            self.set_graph_file(msg.split('=')[0])
        elif 'start' in msg and not self.toggle.isChecked():
            self.toggle.setChecked(True)
            self.activate()
        elif 'stop' in msg and self.toggle.isChecked():
            self.toggle.setChecked(False)
            self.activate()
        elif 'save trace' in msg:
            self.save_trace(os.path.join(self.stats['save_dir'], self.stats['trace_file']))
        elif 'save graph' in msg:
            self.save_graph(os.path.join(self.stats['save_dir'], self.stats['graph_file']))
        elif 'set fadelines' in msg:
            self.set_fadelines()
    
    #### acquisition functions #### 

    def activate(self, toggle=0):
        """Prime the DAQ task for acquisition if it isn't already running.
        Otherwise, stop the task running."""
        if self.toggle.isChecked():
            self.check_settings()
            self.slave = worker(self.stats['Sample Rate (kS/s)']*1e3, self.stats['Duration (ms)']/1e3, self.stats['Trigger Channel'], 
                self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), 
                [ch['range'] for ch in self.stats['channels'].values()])
            remove_slot(self.slave.acquired, self.update_trace, True)
            remove_slot(self.slave.acquired, self.update_graph, True)
            if self.trigger_toggle:
                # remove_slot(self.slave.finished, self.activate, True)
                self.slave.start()
                self.toggle.setText('Stop')
            else: 
                self.toggle.setChecked(False)
                self.slave.analogue_acquisition()
        else:
            # remove_slot(self.slave.finished, self.activate, False)
            self.slave.stop = True
            self.slave.quit()
            self.toggle.setText('Start')

    #### plotting functions ####

    def update_trace(self, data):
        """Plot the supplied data with labels on the trace canvas."""
        t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples)
        i = 0 # index to keep track of which channels have been plotted
        for j in range(8):
            ch = self.channels.cellWidget(j,0).text()
            l = self.lines[j] # shorthand
            if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']:
                try:
                    l.setData(t, data[i])
                except Exception as e:
                    logger.error('DAQ trace could not be plotted.\n'+str(e))
                self.fadelines[j].show()
                l.show()
                self.trace_legend.items[j][0].show()
                self.trace_legend.items[j][1].show()
                i += 1
            else:
                l.hide()
                self.fadelines[j].hide()
                self.trace_legend.items[j][0].hide()
                self.trace_legend.items[j][1].hide()
        self.trace_legend.resize(0,0)
        
    def set_fadelines(self):
        """Take the data from the current lines and sets it to the fadelines."""
        for j in range(8):
            ch = self.channels.cellWidget(j,0).text()
            l = self.lines[j] # shorthand
            if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']:
                try:
                    self.fadelines[j].setData(l.xData, l.yData)
                except Exception as e:
                    logger.error('DAQ trace could not be plotted.\n'+str(e))
                self.fadelines[j].show()
            else:
                self.fadelines[j].hide()
        
    def reset_lines(self):
        """Clear the mean and stdv graphs, reset the legends, then make new 
        lines for each of the slice channels."""
        for legend in self.graph_legends: # reset the legends
            try:
                legend.scene().removeItem(legend)
            except AttributeError: pass
        for g in [self.mean_graph, self.stdv_graph]:
            g.clear()
            g.lines = OrderedDict([])
            self.graph_legends.append(g.addLegend())
            i = 0
            for s in self.dc.slices:
                for chan, val in s.stats.items():
                    g.lines[s.name+'/'+chan] = g.plot([1], name=s.name+'/'+chan, 
                        pen=None, symbol='o', symbolPen=pg.mkPen(pg.intColor(i)),
                        symbolBrush=pg.intColor(i)) 
                    i += 1

    def reset_graph(self):
        """Reset the collection of slice data, then replot the graph."""
        self.dc.reset_arrays()
        self.update_graph()

    def update_graph(self, data=[]):
        """Extract averages from slices of the data.
        Replot the stored data accumulated from averages in slices
        of the measurements."""
        if np.size(data):
            self.dc.process(data, self.stats['n'])
        for s in self.dc.slices:
            for chan, val in s.stats.items():
                self.mean_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['mean'])
                self.stdv_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['stdv'])
                
    def add_horizontal(self, toggle=True):
        """Display a horizontal line on the trace"""
        if toggle: self.hline.show()
        else: 
            self.hline.hide()
            self.hline_label.setText('')
        
    def update_hline(self):
        """Display the value of the horizontal line in the label"""
        self.hline_label.setText(str(self.hline.value()))

    #### save/load functions ####

    def try_browse(self, title='Select a File', file_type='all (*)', 
                open_func=QFileDialog.getOpenFileName, default_path=''):
        """Open a file dialog and retrieve a file name from the browser.
        title: String to display at the top of the file browser window
        default_path: directory to open first
        file_type: types of files that can be selected
        open_func: the function to use to open the file browser"""
        default_path = default_path if default_path else os.path.dirname(self.last_path)
        try:
            if 'PyQt4' in sys.modules:
                file_name = open_func(self, title, default_path, file_type)
            elif 'PyQt5' in sys.modules:
                file_name, _ = open_func(self, title, default_path, file_type)
            if type(file_name) == str: self.last_path = file_name 
            return file_name
        except OSError: return '' # probably user cancelled

    def save_config(self, file_name='daqconfig.dat'):
        """Save the current acquisition settings to the config file."""
        self.stats['config_file'] = file_name if file_name else self.try_browse(
                'Save Config File', 'dat (*.dat);;all (*)', QFileDialog.getSaveFileName)
        try:
            with open(self.stats['config_file'], 'w+') as f:
                for key, val in self.stats.items():
                    if key == 'channels':
                        f.write(key+'='+channel_str(val)+'\n')
                    else:
                        f.write(key+'='+str(val)+'\n')
            logger.info('DAQ config saved to '+self.stats['config_file'])
        except Exception as e: 
            logger.error('DAQ settings could not be saved to config file.\n'+str(e))

    def load_config(self, file_name='daqconfig.dat'):
        """Load the acquisition settings from the config file."""
        self.stats['config_file'] = file_name if file_name else self.try_browse(file_type='dat (*.dat);;all (*)')
        try:
            with open(self.stats['config_file'], 'r') as f:
                for line in f:
                    if len(line.split('=')) == 2:
                        key, val = line.replace('\n','').split('=') # there should only be one = per line
                        try:
                            self.stats[key] = self.types[key](val)
                        except KeyError as e:
                            logger.warning('Failed to load DAQ default config line: '+line+'\n'+str(e))
            self.set_table() # make sure the updates are displayed
            self.set_n(self.stats['n'])
            self.set_save_dir(self.stats['save_dir'])
            self.set_trace_file(self.stats['trace_file'])
            self.set_graph_file(self.stats['graph_file'])
            self.dc.channels = list(self.stats['channels'].keys())
            logger.info('DAQ config loaded from '+self.stats['config_file'])
        except FileNotFoundError as e: 
            logger.warning('DAQ settings could not find the config file.\n'+str(e))

    def save_trace(self, file_name=''):
        """Save the data currently displayed on the trace to a csv file."""
        file_name = file_name if file_name else self.try_browse(
                'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName)
        if file_name:
            # metadata
            header = ', '.join(list(self.stats.keys())) + '\n'
            header += ', '.join(list(map(str, self.stats.values()))[:-1]
                ) + ', ' + channel_str(self.stats['channels']) + '\n'
            # determine which channels are in the plot
            header += 'Time (s)'
            data = []
            for key, d in self.stats['channels'].items():
                if d['plot']:
                    header += ', ' + key # column headings
                    if len(data) == 0: # time (s)
                        data.append(self.lines[int(key[-1])].xData)
                    data.append(self.lines[int(key[-1])].yData) # voltage
            # data converted to the correct type
            out_arr = np.array(data).T
            try:
                np.savetxt(file_name, out_arr, fmt='%s', delimiter=',', header=header)
                logger.info('DAQ trace saved to '+file_name)
            except (PermissionError, FileNotFoundError) as e:
                logger.error('DAQ controller denied permission to save file: \n'+str(e))

    def load_trace(self, file_name=''):
        """Load data for the current trace from a csv file."""
        file_name = file_name if file_name else self.try_browse(file_type='csv(*.csv);;all (*)')
        if file_name:
            head = [[],[],[]] # get metadata
            with open(file_name, 'r') as f:
                for i in range(3):
                    row = f.readline()
                    if row[:2] == '# ':
                        head[i] = row[2:].replace('\n','').split(', ')
            # apply the acquisition settings from the file
            labels = [self.settings.horizontalHeaderItem(i).text() for 
                i in range(self.settings.columnCount())]
            for i in range(len(head[0])):
                try:
                    j = labels.index(head[0][i])
                    self.settings.cellWidget(0,j).setText(head[1][i])
                except ValueError: pass
            self.stats['channels'] = channel_stats(', '.join(head[1][7:]))
            for i in range(8): # whether to plot or not
                ch = self.channels.cellWidget(i,0).text()
                if ch in head[2]:
                    self.channels.cellWidget(i,6).setText('1')
                    self.channels.cellWidget(i,1).setText(self.stats['channels'][ch]['label'])
                else: self.channels.cellWidget(i,6).setText('0')
            self.check_settings()

            # plot the data
            data = np.genfromtxt(file_name, delimiter=',', dtype=float)
            if np.size(data) < 2:
                return 0 # insufficient data to load
            self.update_trace(data.T[1:])

    def save_graph(self, file_name=''):
        """Save the data accumulated from several runs that's displayed in the
        graph into a csv file."""
        file_name = file_name if file_name else self.try_browse(
                'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName)
        if file_name:
            self.dc.save(file_name, list(self.stats.keys()), 
                list(map(str, self.stats.values()))[:-1]
                 + [channel_str(self.stats['channels'])])
            logger.info('DAQ graph saved to '+file_name)
        
    def closeEvent(self, event):
        """Before closing, try to save the config settings to file."""
        statstr = "[[" # dictionary of channel names and properties
        for i in range(self.channels.rowCount()):
            statstr += ', '.join([self.channels.cellWidget(i,j).text() 
                    for j in range(self.channels.columnCount())]) + '],['
        self.stats['channels'] = channel_stats(statstr[:-2] + ']')
        # add all channels to stats
        self.save_config(self.stats['config_file'])
        event.accept()
Exemplo n.º 11
0
    def setupTabs(self):
        #self.tabs.currentChanged.disconnect(self.currentTabChanged)
        while(self.tabs.count() > 0):
            self.tabs.removeTab(0)

        self.tables = {}
        allcounters = Counter.findAll()
        for c in allcounters:
            tab = QWidget(self.tabs)
            hl = QHBoxLayout()
            tab.setLayout(hl)
            
            recordings = Recording.findByIdCounter(c.id)

            tw = QTableWidget(len(recordings), 5)
            self.tables["%i"%c.id] = tw
            column_names = ("Id","Counter", "Date", "Value", "Remove ?")
            tw.setHorizontalHeaderLabels(column_names)

            # Fill the table with the recordings
            for i, r in enumerate(recordings):
                # The id of the recording in the table of recordings
                item = QTableWidgetItem("{}".format(r.id))
                item.setFlags(QtCore.Qt.NoItemFlags)
                tw.setItem (i, 0, item)
                
                # The id of the associated counter
                item = QTableWidgetItem("{}".format(r.idcounter))
                item.setFlags(QtCore.Qt.NoItemFlags)
                tw.setItem (i, 1, item)

                # The date when the recording has been made
                item = QTableWidgetItem(r.date.strftime("%Y-%m-%d %H:%M:%S"))
                item.setFlags(QtCore.Qt.NoItemFlags)
                tw.setItem (i, 2, item)

                # The value can be edited
                item = QTableWidgetItem("{}".format(r.value))
                item.setFlags(QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsEnabled)

                tw.setItem (i, 3, item)

                but = QPushButton("Remove")
                but.clicked.connect(partial(self.on_removeClicked, counter_id=c.id, recording_id=r.id))
                #item = QTableWidgetItem(but)
                #tw.setItem(i, 4, but)
                #tw.setIndexWidget()
                tw.setCellWidget(i, 4, but)

            tw.cellChanged.connect(partial(self.on_cellChanged, counter_id=c.id))

            # We allow sorting and we sort by decreasing date
            # to get the most recent recordings at the top
            tw.setSortingEnabled(True)
            tw.sortByColumn(2, QtCore.Qt.DescendingOrder)

            # Ajust the width of the columns to better see the contents
            tw.resizeColumnsToContents()
            tw.setFixedWidth(600)
            hl.addWidget(tw)

            #### Plot the data
            canvas = self.plot_data(recordings)
            hl.addWidget(canvas)


            self.tabs.addTab(tab,str(c.id) + "-" + c.name)   
Exemplo n.º 12
0
class TableCatalogOTF(QObject):

    runCatalog = pyqtSignal(str)

    def __init__(self):
        def initGui():
            self.tableWidget.setWindowTitle("Catalog OTF")
            self.tableWidget.setSortingEnabled(False)
            msgtrans = QCoreApplication.translate("CatalogOTF", "Layer,Total")
            headers = msgtrans.split(',')
            self.tableWidget.setColumnCount(len(headers))
            self.tableWidget.setHorizontalHeaderLabels(headers)
            self.tableWidget.resizeColumnsToContents()

        super(TableCatalogOTF, self).__init__()
        self.tableWidget = QTableWidget()
        initGui()

    def _getRowLayerID(self, layerID):
        for row in range(self.tableWidget.rowCount()):
            if layerID == self.tableWidget.cellWidget(row, 0).objectName():
                return row
        return -1

    def _changedText(self, layerID, name, column):
        row = self._getRowLayerID(layerID)
        if row != -1:
            wgt = self.tableWidget.cellWidget(
                row, column) if column == 0 else self.tableWidget.item(
                    row, column)
            wgt.setText(name)
            wgt.setToolTip(name)
            self.tableWidget.resizeColumnsToContents()

    @pyqtSlot()
    def _onRunCatalog(self):
        btn = self.sender()
        icon = QIcon(joinPath(dirname(__file__), 'cancel_red.svg'))
        btn.setIcon(icon)
        layerID = btn.objectName()
        self.runCatalog.emit(layerID)

    @pyqtSlot()
    def _onSelectionChanged(self):
        layer = self.sender()
        row = self._getRowLayerID(layer.id())
        if row != -1:
            wgt = self.tableWidget.cellWidget(row, 0)
            nameIcon = 'check_green.svg' if layer.selectedFeatureCount(
            ) == 0 else 'check_yellow.svg'
            icon = QIcon(joinPath(dirname(__file__), nameIcon))
            wgt.setIcon(icon)

    @pyqtSlot("QgsVectorLayer")
    def insertRow(self, layer):
        row = self.tableWidget.rowCount()
        self.tableWidget.insertRow(row)

        column = 0  # Layer
        layerName = layer.name()
        nameIcon = 'check_green.svg' if layer.selectedFeatureCount(
        ) == 0 else 'check_yellow.svg'
        icon = QIcon(joinPath(dirname(__file__), nameIcon))
        btn = QPushButton(icon, layerName, self.tableWidget)
        btn.setObjectName(layer.id())
        btn.setToolTip(layerName)
        btn.clicked.connect(self._onRunCatalog)
        layer.selectionChanged.connect(self._onSelectionChanged)
        self.tableWidget.setCellWidget(row, column, btn)

        column = 1  # Total

        msgtrans = QCoreApplication.translate("CatalogOTF", "None")
        item = QTableWidgetItem(msgtrans)
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableWidget.setItem(row, column, item)

        self.tableWidget.resizeColumnsToContents()

    @pyqtSlot(str)
    def removeRow(self, layerID):
        row = self._getRowLayerID(layerID)
        if row != -1:
            self.tableWidget.removeRow(row)

    @pyqtSlot(str, str)
    def changedNameLayer(self, layerID, name):
        self._changedText(layerID, name, 0)

    @pyqtSlot(str, str)
    def changedTotal(self, layerID, value):
        self._changedText(layerID, value, 1)

    @pyqtSlot(str, bool)
    def changedIconRun(self, layerID, selected):
        row = self._getRowLayerID(layerID)
        if row != -1:
            btn = self.tableWidget.cellWidget(row, 0)
            nameIcon = 'check_green.svg' if not selected else 'check_yellow.svg'
            icon = QIcon(joinPath(dirname(__file__), nameIcon))
            btn.setIcon(icon)
            btn.setEnabled(True)

    @pyqtSlot(str)
    def killed(self, layerID):
        row = self._getRowLayerID(layerID)
        if row != -1:
            btn = self.tableWidget.cellWidget(row, 0)
            btn.setEnabled(False)

    def widget(self):
        return self.tableWidget
Exemplo n.º 13
0
class ThirdPart(QWizardPage):
    def __init__(self):
        super(ThirdPart, self).__init__()
        self.completed = False
        self.setTitle(u'第三方库设置')
        self.setSubTitle(u'需要设置的第三方库')
        rootLayout = QVBoxLayout()
        rootLayout.setContentsMargins(14, 20, 10, 20)

        self.tw_interface = QTableWidget(0, 3)
        headerLabels = QStringList()
        headerLabels.append(u'库名')
        headerLabels.append(u'库路径')
        headerLabels.append(u'打开')
        self.tw_interface.setHorizontalHeaderLabels(headerLabels)
        self.tw_interface.setSelectionBehavior(1)
        self.tw_interface.setRowCount(0)
        self.tw_interface.setColumnWidth(0, 200)
        self.tw_interface.setColumnWidth(1, 280)
        self.tw_interface.horizontalHeader().setStretchLastSection(True)

        self.mhlayout = QHBoxLayout()
        on_new_btn = QPushButton()
        on_new_btn.setText(u'添加类库')
        on_new_btn.clicked.connect(self.on_new)

        on_delete_btn = QPushButton()
        on_delete_btn.setText(u'删除类库')
        on_delete_btn.clicked.connect(self.on_delete)

        space = QSpacerItem(40, 28, QSizePolicy.Expanding)
        self.mhlayout.addSpacerItem(space)
        self.mhlayout.addWidget(on_new_btn)
        self.mhlayout.addWidget(on_delete_btn)

        rootLayout.addWidget(self.tw_interface)
        rootLayout.addLayout(self.mhlayout)
        self.setLayout(rootLayout)
        self.setStyleSheet(sheetstyle)

        self.alloneEnv = os.getenv('ALLONEDIR', '../..').replace('\\', '/')

    def on_new(self):
        rowIndex = self.tw_interface.rowCount()
        self.tw_interface.setRowCount(rowIndex + 1)
        ptn = self.add_button(rowIndex)
        self.tw_interface.setCellWidget(rowIndex, 2, ptn)

    def on_delete(self):
        rowIndex = self.tw_interface.currentRow()
        if rowIndex != -1:
            self.tw_interface.removeRow(rowIndex)

    def updateTable(self, id):
        filePath = QFileDialog.getOpenFileName(self, "请选择库", self.alloneEnv,
                                               "Library(*.lib)")
        if filePath.isEmpty():
            return
        fileinfo = QFileInfo(filePath)
        libPath = fileinfo.absoluteDir().absolutePath()
        libName = fileinfo.baseName()
        # 支持选择文件后与系统ALLONEDIR比较一下变成相对路径
        # 并且能够手动输入相对路径或包含$(ALLONEDIR)的相对路径
        env = QString(os.getenv('ALLONEDIR', '../..').replace('\\', '/'))
        if env.endsWith('/'):
            env.remove(env.lastIndexOf('/'), 1)
        if libPath.contains(env):
            libPath.replace(env, QString('$$ALLONEDIR'))

        self.tw_interface.setItem(id, 1, QTableWidgetItem(libPath))
        self.tw_interface.setItem(id, 0, QTableWidgetItem(libName))

    def add_button(self, id):
        widget = QWidget()
        fileBtn = QPushButton()
        fileBtn.setText(u'浏览...')
        fileBtn.clicked.connect(lambda: self.updateTable(id))
        hLayout = QHBoxLayout()
        hLayout.addWidget(fileBtn)
        hLayout.setAlignment(Qt.AlignHCenter)
        hLayout.setContentsMargins(0, 0, 0, 0)
        widget.setLayout(hLayout)
        return widget

    def initializePage(self):
        super(ThirdPart, self).initializePage()
        self.tw_interface.setRowCount(len(app.g_configurations.thirdpart_lib))
        row = 0
        for libinfo in app.g_configurations.thirdpart_lib:
            twitem0 = QTableWidgetItem(QString(libinfo["libname"]))
            twitem1 = QTableWidgetItem(QString(libinfo["libpath"]))
            self.tw_interface.setItem(row, 0, twitem0)
            self.tw_interface.setItem(row, 1, twitem1)
            ptn = self.add_button(row)
            self.tw_interface.setCellWidget(row, 2, ptn)
            row += 1

    def validatePage(self):
        thirdpart_libs = []
        if self.tw_interface.rowCount() > 0:
            for i in range(self.tw_interface.rowCount()):
                libinfo = {"libname": "", "libpath": ""}
                libname = self.tw_interface.item(i, 0).text()
                libpath = self.tw_interface.item(i, 1).text()
                #print unicode(libname)
                #print unicode(libpath)
                libinfo["libname"] = unicode(libname)
                libinfo["libpath"] = unicode(libpath)
                thirdpart_libs.append(libinfo)

        print thirdpart_libs
        app.g_configurations.thirdpart_lib = thirdpart_libs
        return True
Exemplo n.º 14
0
class AccessFrontend(ScrollArea):
    COMPONENT = 'access'
    LABEL = tr('Access to services')
    REQUIREMENTS = ('access',)
    STYLE_ALLOW = "color: white; background-color: white; border: none;"
    STYLE_DISALLOW = "color: lightGray; background-color: lightGray; border: none;"
    ICON = ':/icons/Acl.png'

    def __init__(self, client, parent):
        ScrollArea.__init__(self)

        self.client = client
        self.mainwindow = parent
        self._modified = False
        self.__disabled = False
        self.net_object = QNetObject.getInitializedInstance(self.client)
        if EDENWALL:
            self.vpn_object = QOpenVpnObject.getInstance()

        self.setupWidgets()
        self.getConfigs()
        self.getNetworks()
        # vpn_config is used to check if the VPN config changed or not
        self.vpn_config = self.getVPNConfig()
        self.fillTable()
        self.net_object.registerCallbacks(self.validateNetCfg, self.updateWithNetCfg)
        if EDENWALL:
            self.vpn_object.registerCallbacks(self.validateVpnCfg, self.updateWithVpnCfg)


        self.mainwindow.addToInfoArea(tr("Access interface enabled"))

    @staticmethod
    def get_calls():
        """
        services called at startup (self.mainwindow.init_call)
        """
        return (('access', 'getConfig'),)

    def getVPNConfig(self):
        if not EDENWALL:
            return None
        vpn = self.vpn_object.getCfg()
        if not vpn:
            return None
        return (vpn.enabled, vpn.protocol, vpn.port, vpn.client_network)

    def setupWidgets(self):
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        self.icon = QIcon()
        ALLOW = QPixmap(":/icons-20/status_on.png")
        self.icon.addPixmap(ALLOW, QIcon.Normal, QIcon.On)
        DISALLOW = QPixmap(":/icons-20/status_off.png")
        self.icon.addPixmap(DISALLOW, QIcon.Normal, QIcon.Off)

        title = QLabel(u"<H1>%s</H1>" % tr("Access to services"))
        layout.addWidget(title)

        self.table = QTableWidget()
        self.table.setSelectionMode(QAbstractItemView.NoSelection)

        layout.addWidget(self.table)

    def isModified(self):
        return self._modified

    def isValid(self):
        if self.__disabled:
            return True
        valid, errmsg = self.access_cfg.isValidWithMsg()
        if not valid:
            self.error_message = errmsg
        return valid

    def setModified(self, modif=True):
        if self.__disabled:
            self._modified = False
            return
        self._modified = modif
        if modif:
            self.mainwindow.setModified(self, True)

    def resetConf(self):
        if self.__disabled:
            return
        self.getConfigs()
        self.getNetworks()
        self.fillTable()

    def __disable(self, reason):
        if self.__disabled:
            return
        self.__disabled = True
        self.mainwindow.addToInfoArea(
            tr("The Access to services interface is disabled."),
            COLOR_ERROR)
        self.mainwindow.addToInfoArea(reason, COLOR_ERROR)
        self.close()
        raise NuConfModuleDisabled(reason)

    def getConfigs(self):
        if self.__disabled:
            return
        try:
            data = self.mainwindow.init_call('access', 'getConfig')
        except RpcdError:
            self.__disable(tr("Could not get Access to services configuration."))
            return
        if data is None:
            self.access_cfg = AccessConf.defaultConf()
        else:
            self.access_cfg = AccessConf.deserialize(data)

    def _getNetworks(self, netcfg):
        return [(interface.system_name, network)
            for interface, network in netcfg.iterKnownNetworks()]

    def getNetworks(self):
        if self.__disabled:
            return
        netcfg = QNetObject.getInstance().netcfg
        if netcfg is None:
            self.networks = ()
            self.mainwindow.addToInfoArea(
                tr("The access interface could not load the network configuration"),
                COLOR_ERROR
                )
            return
        # list of (interface, network) where interface (str) is the system
        # name, and network (IPy.IP object) is the network address
        # (eg. IP('192.168.0.0/24')
        self.networks = self._getNetworks(netcfg)
        self.networks += list(self.access_cfg.custom_networks)
        self.networks.sort()

    def fillTable(self):
        if self.__disabled:
            self.table.clear()
            return
        services = list(self.access_cfg.permissions)
        self.table.clear()

        # (interface (str), network (IPy), ip version (int)) => row (int)
        # Don't use (interface, network) because of a bug in IPy < 0.70:
        # IP('0.0.0.0/0') and IP('::/0') are considered as equal
        self.net_to_row = {}

        component_to_name = ComponentToName()
        self.table.setSortingEnabled(False)
        self.table.setRowCount(len(self.networks))
        self.setVerticalHeaders()
        self.table.setColumnCount(len(services))
        self.table.setHorizontalHeaderLabels([component_to_name.display_name(service) for service in services])
        self.table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)

        for irow, interface_network in enumerate(self.networks):
            self.setRow(interface_network, irow)
            for icol, service in enumerate(self.access_cfg.permissions):
                allow = interface_network in self.access_cfg.permissions[service]
                self.createService(irow, icol, service, interface_network, allow)

    def getRow(self, interface_network, pop=False):
        interface, network = interface_network
        key = (interface, network, network.version())
        if pop:
            return self.net_to_row.pop(key)
        else:
            return self.net_to_row[key]

    def setRow(self, interface_network, row):
        interface, network = interface_network
        key = (interface, network, network.version())
        self.net_to_row[key] = row

    def setVerticalHeaders(self):
        labels = [self.netLabel(interface, network)
            for interface, network in self.networks]
        self.table.setVerticalHeaderLabels(labels)

    def saveConf(self, message):
        data = self.access_cfg.serialize(downgrade=True)
        self.client.call("access", 'setConfig', message, data)
        self.setModified(False)

    def changeService(self, col, service, interface_network):
        row = self.getRow(interface_network)
        self.setModified(True)
        button = self.table.cellWidget(row, col)
        if button.isChecked():
            self.access_cfg.permissions[service].add(interface_network)
            button.setStyleSheet(self.STYLE_ALLOW)
        else:
            try:
                self.access_cfg.permissions[service].remove(interface_network)
            except KeyError:
                pass
            button.setStyleSheet(self.STYLE_DISALLOW)

    def appendNetwork(self, interface_network, close_all_ports=False):
        row = self.table.rowCount()
        self.table.insertRow(row)
        self.networks.append(interface_network)
        self.setRow(interface_network, row)
        interface, network = interface_network
        for icol, service in enumerate(self.access_cfg.permissions):
            if (not close_all_ports) \
            and (service in OPEN_BY_DEFAULT) \
            and (network not in CLOSED_NETWORKS):
                allow = True
                self.access_cfg.permissions[service].add(interface_network)
            else:
                allow = interface_network in self.access_cfg.permissions[service]
            self.createService(row, icol, service, interface_network, allow)

    def removeNetwork(self, interface_network):
        index = self.getRow(interface_network, pop=True)
        self.table.removeRow(index)
        network = self.networks[index]
        for service, networks in self.access_cfg.permissions.iteritems():
            try:
                networks.remove(network)
            except KeyError:
                pass
        del self.networks[index]
        for key, row in self.net_to_row.iteritems():
            if row > index:
                self.net_to_row[key] -= 1

    # callback used to update the table on network modification
    def updateWithNetCfg(self, deleted_nets, added_nets):
        if not(deleted_nets or added_nets):
            return

        # delete
        for key in deleted_nets:
            self.removeNetwork(key)

        # add new
        for interface_network in added_nets:
            self.appendNetwork(interface_network, close_all_ports=True)

        # modify and update
        self.setVerticalHeaders()
        self.setModified(True)

    def createService(self, row, col, service, interface_network, allow):
        button = QPushButton(self.icon, u'')
        button.setCheckable(True)
        button.setFlat(True)
        button.setAutoFillBackground(True)
        if allow:
            style = self.STYLE_ALLOW
        else:
            style = self.STYLE_DISALLOW
        button.setStyleSheet(style)
        button.setFocusPolicy(Qt.NoFocus)

        self.mainwindow.writeAccessNeeded(button)
        self.connect(button, SIGNAL('clicked()'), partial(self.changeService, col, service, interface_network))
        self.table.setCellWidget(row, col, button)

        # with PyQt 4.4.2, table.setCellWidget(button) changes
        # the button's state (bug fixed in PyQt 4.4.4)
        button.setChecked(allow)

    # callback used when the networks are modified
    def validateNetCfg(self):
        netcfg = QNetObject.getInstance().netcfg

        previous_nets = set(self.networks) - set(self.access_cfg.custom_networks)
        new_networks = self._getNetworks(netcfg)
        new_networks = set(new_networks)

        not_in_both = previous_nets ^ new_networks
        deleted_nets = not_in_both & previous_nets
        added_nets = not_in_both & new_networks
        return True, deleted_nets, added_nets

    def validateVpnCfg(self):
        """
        always accept modifications
        """
        return True, self.getVPNConfig()

    def updateWithVpnCfg(self, new_config):
        if self.vpn_config == new_config:
            return

        # anything changed, access has to reapply the new config
        self.setModified()
        self.vpn_config = new_config

        # get old/new key
        config = self.vpn_object.getCfg()
        if self.access_cfg.custom_networks:
            old_key = self.access_cfg.custom_networks[0]
        else:
            old_key = None
        if config.enabled:
            network = config.client_network
            try:
                network = IP(network)
            except ValueError:
                # ignore invalid network: vpn check will raise an error
                return
            new_key = (OPENVPN_INTERFACE, network)
        else:
            new_key = None

        # no change? exit
        if old_key == new_key:
            return

        # create/delete vpn custom network
        if old_key:
            self.removeNetwork(old_key)
        if new_key:
            self.access_cfg.custom_networks = [new_key]
            self.appendNetwork(new_key)
        else:
            self.access_cfg.custom_networks = []
        self.setVerticalHeaders()

    def netLabel(self, interface, network):
        """
        return label for network
        """
        interface_label = interface
        network_label = str(network)
        network = IP(network)
        netcfg = QNetObject.getInstance().netcfg
        try:
            interface = netcfg.getInterfaceBySystemName(interface)
            interface_label = interface.user_label

            network = netcfg.getNet(network)
            network_label = network.displayName()
        except NoMatch:
            pass
        return tr("%s: %s") % (interface_label, network_label)