Beispiel #1
0
class MemDumpWindow(QWidget):

    kill_signal = Signal(bool)

    def __init__(self, qmp, base=0, max=constants['block_size']):
        super().__init__()

        self.flag = False
        self.threshold = 2048 # number of resident bytes

        self.qmp = qmp
        self.init_ui()

        self.baseAddress = base
        self.maxAddress = self.baseAddress

        self.delta = 4 # adds a small buffer area for scrolling action to happen

        self.sem = QSemaphore(1) # semaphore for controlling access to the enabling / disabling of the scroll listening
        self.pos = self.chr_display.verticalScrollBar().value()

        self.highlight_sem = QSemaphore(1) # semaphore for controlling access to highlighting state
        self.is_highlighted = False
        self.highlight_addr = 0

        self.endian = Endian.little
        self.endian_sem = QSemaphore(1)

        self.hash = randint(0, 0xfffffffffffffff)

        icon = QIcon('package/icons/nasa.png')
        self.setWindowIcon(icon)

        self.max_size = 0xfffffffffffffff

        self.qmp.pmem.connect(self.update_text)
        self.grab_data(val=self.baseAddress, size=min(max, constants['block_size'] + base)-self.baseAddress)

        self.t = MyThread(self)
        self.t.timing_signal.connect(lambda:self.grab_data(val=self.baseAddress, size=self.maxAddress-self.baseAddress, grouping=self.grouping.currentText(), refresh=True))
        self.qmp.stateChanged.connect(self.t.halt)
        self.t.running = self.qmp.running
        self.t.start()

        self.show()
        

    def init_ui(self):   
        self.hbox = QHBoxLayout() # holds widgets for refresh button, desired address, and size to grab
        self.vbox = QVBoxLayout() # main container
        self.lower_hbox = QSplitter() # holds memory views
        self.lower_container = QHBoxLayout() # holds  lower_hbox and the endian_vbox
        self.endian_vbox = QVBoxLayout()

        self.hbox.addWidget(QLabel('Address:'))
        self.address = QLineEdit()
        self.hbox.addWidget(self.address)

        self.hbox.addWidget(QLabel('Size:'))
        self.size = QLineEdit()
        self.hbox.addWidget(self.size)

        self.hbox.addWidget(QLabel('Grouping:'))
        self.grouping = QComboBox()
        self.grouping.addItems(['1','2','4','8'])
        self.hbox.addWidget(self.grouping)

        self.search = QPushButton('Search')
        self.search.clicked.connect(lambda:self.find(self.address.text(), constants['block_size']))
        self.hbox.addWidget(self.search)

        self.refresh = QPushButton('Refresh')
        self.refresh.clicked.connect(lambda:self.grab_data(val=self.address.text(), size=self.size.text(), grouping=self.grouping.currentText(), refresh=True))
        self.hbox.addWidget(self.refresh)

        self.save = QPushButton('Save')
        self.save.clicked.connect(lambda: self.save_to_file())
        self.disable_save(self.qmp.running)
        self.qmp.stateChanged.connect(self.disable_save)
        self.hbox.addWidget(self.save)

        self.auto_refresh = QCheckBox('Auto Refresh')
        self.auto_refresh.setCheckState(Qt.CheckState.Checked)
        self.auto_refresh.stateChanged.connect(self.auto_refresh_check)
        self.hbox.addWidget(self.auto_refresh)

        self.vbox.addLayout(self.hbox)
        
        # textbox for addresses
        self.addresses = QTextEdit()
        self.addresses.setReadOnly(True)
        self.addresses.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.addresses.setLineWrapMode(QTextEdit.NoWrap)
        self.addresses.setCurrentFont(QFont('Courier New'))
        self.addresses.setGeometry(0,0,150,500)
        self.lower_hbox.addWidget(self.addresses)

        # textbox for hex display of memory
        self.mem_display = QTextEdit()
        self.mem_display.setReadOnly(True)
        self.mem_display.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.mem_display.setLineWrapMode(QTextEdit.NoWrap)
        self.mem_display.setCurrentFont(QFont('Courier New'))
        self.mem_display.setGeometry(0,0,600,500)
        self.lower_hbox.addWidget(self.mem_display)
        
        # textbox for char display of memory
        self.chr_display = QTextEdit()
        self.chr_display.setReadOnly(True)
        self.chr_display.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.chr_display.setLineWrapMode(QTextEdit.NoWrap)
        self.chr_display.setCurrentFont(QFont('Courier New'))
        self.mem_display.setGeometry(0,0,400,500)
        self.lower_hbox.addWidget(self.chr_display)

        self.lower_container.addWidget(self.lower_hbox)

        self.mem_display.verticalScrollBar().valueChanged.connect(self.addresses.verticalScrollBar().setValue) #synchronizes addresses's scroll bar to mem_display's 
        self.addresses.verticalScrollBar().valueChanged.connect(self.mem_display.verticalScrollBar().setValue) #synchronizes mem_display's scroll to addresses's, allowing for searching for addresses to scrol mem_display to the desired point 
        self.chr_display.verticalScrollBar().valueChanged.connect(self.mem_display.verticalScrollBar().setValue)  
        self.mem_display.verticalScrollBar().valueChanged.connect(self.chr_display.verticalScrollBar().setValue)  

        self.chr_display.verticalScrollBar().valueChanged.connect(self.handle_scroll) # allows us to do scrolling

        # setting up endiannes selection buttons
        self.little = QRadioButton("Little Endian")
        self.little.click()
        self.little.clicked.connect(lambda:self.change_endian(Endian.little))
        self.big = QRadioButton("Big Endian")
        self.big.clicked.connect(lambda:self.change_endian(Endian.big))
        self.endian_vbox.addWidget(self.little)
        self.endian_vbox.addWidget(self.big)
        self.endian_vbox.addSpacing(400)

        self.lower_container.addLayout(self.endian_vbox)

        self.vbox.addLayout(self.lower_container)
        self.vbox.setSpacing(10)
        self.setLayout(self.vbox)
        self.setWindowTitle("Memory Dump")
        self.setGeometry(100, 100, 1550, 500)

    def disable_save(self, val):
        self.save.setEnabled(not val)

    def save_to_file(self):
        try:
            filename = QFileDialog().getSaveFileName(self, 'Save', '.', options=QFileDialog.DontUseNativeDialog)
        except Exception as e:
            return

        if filename[0] == '':
            return

        args = {
            'val': self.baseAddress,
            'size': self.maxAddress - self.baseAddress,
            'filename': filename[0]
        }

        self.qmp.command('pmemsave', args=args)
        



    def auto_refresh_check(self, value):
        if self.auto_refresh.checkState() == Qt.CheckState.Checked and not self.t.isRunning():
            self.t = MyThread(self)
            self.t.timing_signal.connect(lambda:self.grab_data(val=self.baseAddress, size=self.maxAddress-self.baseAddress, grouping=self.grouping.currentText(), refresh=True))
            self.t.start()
        elif self.auto_refresh.checkState() == Qt.CheckState.Unchecked:
            self.kill_signal.emit(True)


    def closeEvent(self, event):
        self.kill_signal.emit(True)
        self.qmp.pmem.disconnect(self.update_text)
        while True:
            if self.sem.tryAcquire(1, 1):
                break
            self.sem.release(10)
        event.accept()


    def update_text(self, value):
        if not value or value['hash'] != self.hash: # semaphore must be held before entering this function
            return
        byte = value['vals']
        if self.refresh:
            self.clear_highlight()
            self.addresses.clear()  # clearing to refresh data, other regions will be refilled through scrolling
            self.mem_display.clear()
            self.chr_display.clear()
            
        s = [''] * ceil((len(byte) / (16))) # hex representation of memory
        addresses =  '' # addresses
        count = self.baseAddress # keeps track of each 16 addresses
        if self.pos == self.max:  # scrolling down
            count = self.maxAddress 

        self.maxAddress = max(count + (len(byte)), self.maxAddress)
 

        first = True
        chars = [''] * len(s) # char represenation of memory
        index = 0
        self.endian_sem.acquire()
        nums = ''
        for tup in byte:
            b = tup['val']
            if count % 16 == 0:
                if first:
                    addresses += f'0x{count:08x}' 
                    first = False
                else:
                    addresses += f'\n0x{count:08x}' 

                    index += 1
            count += 1
             
            if self.endian == Endian.big:
                if tup['ismapped']:
                    nums = f'{b:02x}' + nums
                    chars[index] += f'{char_convert(b):3}'
                else:
                    nums = '**' + nums
                    chars[index] += f'{".":3}'

            elif self.endian == Endian.little:  
                if tup['ismapped']:     
                    nums += f'{b:02x}'      
                    chars[index] = f'{char_convert(b):3}' + chars[index]
                else:
                    nums = '**' + nums
                    chars[index] = f'{".":3}' + chars[index]

            if count % self.group == 0:
                if self.endian == Endian.big:
                    s[index] += nums + ' '
                elif self.endian == Endian.little:
                     s[index] = nums + ' ' + s[index]
                nums = ''
                #print(f'"{s[index]}"')
        self.endian_sem.release()

        s = '\n'.join(s)
        chars = '\n'.join(chars)

        scroll_goto = self.pos

        if self.pos > self.max - self.delta:  # scrolling down
            self.addresses.append(addresses)
            self.mem_display.append(s)
            self.chr_display.append(chars)
            if self.flag:
                self.flag = False
                scroll_goto = (1 - constants['block_size'] / self.threshold) * self.max
            else:
                scroll_goto = self.max

        elif self.pos < self.min + self.delta:    # scrolling  up
            addr_cur = self.addresses.textCursor()
            mem_cur = self.mem_display.textCursor()
            chr_cur = self.chr_display.textCursor()

            addr_cur.setPosition(0)
            mem_cur.setPosition(0)
            chr_cur.setPosition(0)

            self.addresses.setTextCursor(addr_cur)
            self.mem_display.setTextCursor(mem_cur)
            self.chr_display.setTextCursor(chr_cur)

            self.addresses.insertPlainText(addresses + '\n')
            self.mem_display.insertPlainText(s + '\n')
            self.chr_display.insertPlainText(chars + '\n')
            
            if self.flag:
                self.flag = False
                scroll_goto = (constants['block_size'] / self.threshold) * self.max
            else:
                scroll_goto = self.chr_display.verticalScrollBar().maximum() - self.max

        else:
            self.addresses.setPlainText(addresses)
            self.mem_display.setPlainText(s)
            self.chr_display.setPlainText(chars)

        self.highlight_sem.acquire()
        if self.is_highlighted:
            self.highlight_sem.release()
            self.highlight(self.highlight_addr, self.group)
        else:
            self.highlight_sem.release()

        self.chr_display.verticalScrollBar().setValue(scroll_goto)
        self.chr_display.verticalScrollBar().valueChanged.connect(self.handle_scroll)
        self.sem.release()


    def grab_data(self, val=0, size=constants['block_size'], grouping=1, refresh=False):       
        if val == None:
            val = 0
        if size == None:
            size = 1024

        if type(val) == str:
            try:
                val = int(val, 0)
            except Exception:
                val = 0
        
        if type(size) == str:
            try:
                size = int(size, 0)
            except Exception:
                size = constants['block_size']

        if type(grouping) == str:
            try:
                grouping = int(grouping, 0)
            except:
                grouping = 1

        if grouping not in [1, 2, 4, 8]:
            grouping = 1

        if val < 0:
            val = 0
        if val >= self.max_size:
            return
        if size < 0:
            size = constants['block_size']
        if size > self.threshold:
            size = self.threshold
        

        self.sem.acquire()

        val = val - (val % 16)
        if val < self.baseAddress or refresh:
            self.baseAddress = val
        if size % 16 != 0:
            size = size + (16 - (size % 16))
        if val + size > self.max_size:
            size = self.max_size - val
        
        try:
            self.chr_display.verticalScrollBar().valueChanged.disconnect(self.handle_scroll)
        except:
            pass
        self.pos = self.chr_display.verticalScrollBar().value()
        self.max = self.chr_display.verticalScrollBar().maximum()
        self.min = self.chr_display.verticalScrollBar().minimum()
        self.group = grouping

        self.refresh = refresh
        if refresh: 
            self.maxAddress = self.baseAddress
            
            self.highlight_sem.acquire()
            if self.is_highlighted and self.highlight_addr not in range(val, val + size):
                self.is_highlighted = False
                self.pos = 0
            self.highlight_sem.release()

        args = {
                'addr': val,
                'size': size,
                'hash': self.hash,
                'grouping': 1
                }
        self.qmp.command('get-pmem', args=args)


    def find(self, addr, size):
        try:
            addr = int(addr, 0)
        except ValueError as e:
            print(e)
            return
        if self.baseAddress <= addr and addr <= self.maxAddress:
            group = self.grouping.currentText()
            try:
                group = int(group, 0)
                if group not in [1, 2, 4, 8]:
                    group = 1
            except:
                group = 1
            self.highlight(addr, group)
            
        else:
            self.highlight_sem.acquire()
            self.is_highlighted = True
            self.highlight_addr = addr
            self.highlight_sem.release()
            self.grab_data(val=addr, size=size, refresh=True )


    def clear_highlight(self):
        fmt = QTextCharFormat()
        fmt.setFont('Courier New')
        # clearing past highlights
        addr_cur = self.addresses.textCursor()  # getting cursors
        mem_cur = self.mem_display.textCursor()
        chr_cur = self.chr_display.textCursor()

        addr_cur.select(QTextCursor.Document)   # selecting entire document
        mem_cur.select(QTextCursor.Document)
        chr_cur.select(QTextCursor.Document)
        
        addr_cur.setCharFormat(fmt) # adding format
        mem_cur.setCharFormat(fmt)
        chr_cur.setCharFormat(fmt)


    def highlight(self, addr, group):
        self.clear_highlight()
        
        # adding new highlights
        fmt = QTextCharFormat()
        fmt.setBackground(Qt.cyan)
        fmt.setFont('Courier New')

        addr_block = self.addresses.document().findBlockByLineNumber((addr - self.baseAddress) // 16) # gets linenos 
        mem_block = self.mem_display.document().findBlockByLineNumber((addr - self.baseAddress) // 16)
        chr_block = self.chr_display.document().findBlockByLineNumber((addr - self.baseAddress) // 16)

        addr_cur = self.addresses.textCursor()  # getting cursors
        mem_cur = self.mem_display.textCursor()
        chr_cur = self.chr_display.textCursor()


        char_offset = 0
        mem_offset = 0
        self.endian_sem.acquire()
        if self.endian == Endian.big:
            mem_offset = ((addr % 16) // group) * (2 * group + 1)
            char_offset = (addr % 16) * 3
        elif self.endian == Endian.little:
            mem_offset = (((16 / group) - 1 )* (2 * group + 1)) - ((addr % 16) // group) * (2 * group + 1)
            char_offset = (15*3) - ((addr % 16) * 3)
        self.endian_sem.release()
        addr_cur.setPosition(addr_block.position()) # getting positions
        mem_cur.setPosition(mem_block.position() + mem_offset) # gives character offset within 16 byte line
        chr_cur.setPosition(chr_block.position() + char_offset) # sets position of char

        chr_text = self.chr_display.toPlainText()
        if chr_text[chr_cur.position()] == '\\' and chr_cur.position() + 1 < len(chr_text) and chr_text[chr_cur.position() + 1] in ['0', 'n', 't']:
            chr_cur.setPosition(chr_cur.position() + 2, mode=QTextCursor.KeepAnchor) 
        else:
            chr_cur.setPosition(chr_cur.position() + 1, mode=QTextCursor.KeepAnchor) 


        addr_cur.select(QTextCursor.LineUnderCursor)    # selects whole line
        mem_cur.select(QTextCursor.WordUnderCursor)     # selects just one word

        addr_cur.setCharFormat(fmt) # setting format
        mem_cur.setCharFormat(fmt)
        chr_cur.setCharFormat(fmt)

        self.addresses.setTextCursor(addr_cur)
        self.mem_display.setTextCursor(mem_cur)
        self.chr_display.setTextCursor(chr_cur)
        
        self.highlight_sem.acquire()
        self.is_highlighted = True
        self.highlight_addr = addr
        self.highlight_sem.release()


    def handle_scroll(self):
        if self.baseAddress > 0 and self.chr_display.verticalScrollBar().value() < self.chr_display.verticalScrollBar().minimum() + self.delta:
            size = constants['block_size']
            if self.maxAddress - self.baseAddress >= self.threshold:
                self.flag = True
                self.grab_data(val=self.baseAddress - constants['block_size'], size=self.threshold, refresh=True, grouping=self.grouping.currentText())
                return
            if self.baseAddress < size:
                size = self.baseAddress
            self.grab_data(val=self.baseAddress-size, size=size, grouping=self.grouping.currentText())
        elif self.chr_display.verticalScrollBar().value() > self.chr_display.verticalScrollBar().maximum() - self.delta and self.maxAddress <= self.max_size:
            if self.maxAddress - self.baseAddress >= self.threshold:
                self.flag = True
                self.grab_data(val=self.baseAddress + constants['block_size'], size=self.threshold, refresh=True, grouping=self.grouping.currentText())
            else:
                self.grab_data(val=self.maxAddress, grouping=self.grouping.currentText())
      
      
    def change_endian(self, endian):
        self.endian_sem.acquire()
        if endian == Endian.little:
            self.endian = endian
        elif endian == Endian.big:
            self.endian = endian
        self.endian_sem.release()
Beispiel #2
0
class mainWindow(QObject):

    signalRun = Signal(SpiderThread)
    signalRunApi = Signal(apiTester)
    def __init__(self):
        QObject.__init__(self)  # must init parent QObject,if you want to use signal
        self.widget = QWidget()
        self.ipLabel = QLabel(self.widget)
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.man = SpiderThread()
        self.api = apiTester()
        # 1 2:loop 3: time
        self.testStatus = [False,1,0,"ip","mac"]

        # advance config
        self.findCoreStop = True
        self.cleanCacheSet = False
        self.useApiTest = False
        self.showTestProgress = True
        self.saveTestLog = False
        self.saveLogPath = ""
        self.chromePath =  ""
        self.showChrome = False
        self.coreDumpPath = ""

        # ui form
        self.passwordLabel = QLabel(self.widget)

        self.ipLineEdit = QLineEdit(self.widget)
        self.passwordLineEdit = QLineEdit(self.widget)

        self.startBtn = QPushButton(self.widget)
        self.stopBtn = QPushButton(self.widget)

        self.messageBox = QTextEdit(self.widget)
        self.messageBox.setReadOnly(True)

        self.userLabel = QLabel(self.widget)
        self.userLineEdit = QLineEdit(self.widget)

        self.intervalLabel = QLabel(self.widget)
        self.intervalSpinBox = QSpinBox(self.widget)

        self.loopLabel = QLabel(self.widget)
        self.loopSpinBox = QSpinBox(self.widget)

        self.intervalSpinBox.setRange(0,9999)
        self.loopSpinBox.setRange(1,9999)

        self.radioReboot = QRadioButton(self.widget)
        self.radioProvision = QRadioButton(self.widget)
        self.radioFactory = QRadioButton(self.widget)

        # self.apiCheckBox = QCheckBox(self.widget)

        self.menu = QMenu()
        self.gxpAction = QAction("Classic UI")
        self.grp2602Action = QAction("Ant Design UI")
        self.gxpAction.setCheckable(True)
        self.grp2602Action.setCheckable(True)
        self.menu.addAction(self.gxpAction)
        self.menu.addAction(self.grp2602Action)
        self.webLabel = QLabel(self.widget)
        self.webBtn = QPushButton(self.widget)
        self.webBtn.setMenu(self.menu)
        self.clearBtn = QPushButton(self.widget)
        self.messageList = deque()
        self.timer = QTimer()


        self.advanceBtn = QPushButton(self.widget)
        self.infoLabel = QLabel(self.widget)

        # provision widget
        self.provWidget = QWidget(self.widget)
        self.ver1Label = QLabel(self.provWidget)
        self.ver2Label = QLabel(self.provWidget)
        self.ver3Label = QLabel(self.provWidget)
        self.ver1LineEdit = QLineEdit(self.provWidget)
        self.ver2LineEdit = QLineEdit(self.provWidget)
        self.ver3LineEdit = QLineEdit(self.provWidget)

        self.dir1Label = QLabel(self.provWidget)
        self.dir2Label = QLabel(self.provWidget)
        self.dir3Label = QLabel(self.provWidget)
        self.dir1LineEdit = QLineEdit(self.provWidget)
        self.dir2LineEdit = QLineEdit(self.provWidget)
        self.dir3LineEdit = QLineEdit(self.provWidget)

        self.radioHttp = QRadioButton(self.provWidget)
        self.radioHttps = QRadioButton(self.provWidget)
        self.radioTftp = QRadioButton(self.provWidget)
        self.radioFtp = QRadioButton(self.provWidget)
        self.radioFtps = QRadioButton(self.provWidget)
        self.radioWindow = QRadioButton(self.provWidget)

        # advance widget
        self.advanceWidget = QWidget()
        self.checkCoreBox = QCheckBox(self.advanceWidget)
        self.cleanCache = QCheckBox(self.advanceWidget)
        self.checkSaveLogBox = QCheckBox(self.advanceWidget)
        self.selectDirBtn = QPushButton(self.advanceWidget)
        self.saveDirLabel = QLabel(self.advanceWidget)
        self.saveDirLabel.setStyleSheet("background:white")
        self.checkProgressBox = QCheckBox(self.advanceWidget)
        self.advanceOkBtn = QPushButton(self.advanceWidget)
        self.selectChromeBtn = QPushButton(self.advanceWidget)
        self.chromePathLabel = QLabel(self.advanceWidget)
        self.chromePathLabel.setStyleSheet("background:white")
        self.checkShowChromeBox = QCheckBox(self.advanceWidget)
        self.chromeLabel = QLabel(self.advanceWidget)
        self.pcapLabel = QLabel(self.advanceWidget)
        self.apiCheckBox = QCheckBox(self.advanceWidget)
        self.corePathLabel = QLabel(self.advanceWidget)
        self.corePathLabel.setStyleSheet("background:white")
        self.corePathBtn = QPushButton(self.advanceWidget)

        self.interfaceMenu = QComboBox(self.advanceWidget)
        self.interfaceMenu.addItem('Default')

        self.aiOptionBox= QCheckBox(self.advanceWidget)

        a = IFACES
        print(a)
        for i in a.keys():
            print(a[i].description)
            self.interfaceMenu.addItem(a[i].description)

        # connect singal and slot
        self.startBtn.clicked.connect(self.clickedStarBtn)
        self.radioProvision.clicked.connect(self.clickedProvision)
        self.radioReboot.clicked.connect(self.clickedOthers)
        self.radioFactory.clicked.connect(self.clickedOthers)
        self.stopBtn.clicked.connect(self.clickedStopBtn)
        self.grp2602Action.triggered.connect(self.clickedGrp2602)
        self.gxpAction.triggered.connect(self.clickedGxpType)
        self.timer.timeout.connect(self.updateMessage)
        self.apiCheckBox.stateChanged.connect(self.apiTestBoxCheck)
        self.clearBtn.clicked.connect(self.clickedClearBtn)

        self.advanceBtn.clicked.connect(self.clickedAdvanceBtn)
        self.advanceOkBtn.clicked.connect(self.clickedAdvanceOkBtn)
        self.checkSaveLogBox.stateChanged.connect(self.saveLogBoxCheck)
        self.selectChromeBtn.clicked.connect(self.clickedSelectChromeBtn)
        self.selectDirBtn.clicked.connect(self.clickedSelectDirBtn)
        self.corePathBtn.clicked.connect(self.clickedCorePathBtn)

        self.worker.signalJobEnd.connect(self.slotTestStoped)
        self.worker.apiTestFinished.connect(self.slotTestStoped)
        self.signalRun.connect(self.worker.dowork)
        self.signalRunApi.connect(self.worker.doworkApi)

        # self.man.signalUpdateMessage.connect(self.pushMessage)

    def setupUI(self):
        # set text content /value
        self.widget.setWindowTitle("自动重启升降级测试工具")
        self.ipLabel.setText("初始IP:")
        self.passwordLabel.setText("密码:")
        self.startBtn.setText("开始测试")
        self.stopBtn.setText("停止测试")
        self.userLabel.setText("用户名:")
        self.intervalLabel.setText("间隔时间:")
        self.loopLabel.setText("测试次数:")
        self.intervalSpinBox.setValue(130)
        self.radioFactory.setText("恢复出厂")
        self.radioProvision.setText("升降级")
        self.radioReboot.setText("重启")
        self.ver1Label.setText("版本 1:")
        self.ver2Label.setText("版本 2:")
        self.ver3Label.setText("版本 3:")
        self.dir1Label.setText("路径 1:")
        self.dir2Label.setText("路径 2:")
        self.dir3Label.setText("路径 3:")
        self.radioHttp.setText("Http")
        self.radioHttps.setText("Https")
        self.radioTftp.setText("Tftp")
        self.radioFtp.setText("Ftp")
        self.radioFtps.setText("Ftps")
        self.apiCheckBox.setText("使用API测试,配置CoreDump下载路径")
        self.webLabel.setText("网页类型:")
        self.webBtn.setText("请选择UI类型")
        self.clearBtn.setText("清空输入")

        self.advanceWidget.setWindowTitle("高级设置")
        self.advanceBtn.setText("高级设置")
        self.checkCoreBox.setText("发现Core Dump时停止测试")
        self.cleanCache.setText("清除页面cache")
        self.checkSaveLogBox.setText("保存测试日志")
        self.selectDirBtn.setText("浏览")
        self.checkProgressBox.setText("显示底部状态条")
        self.advanceOkBtn.setText("OK")
        self.checkShowChromeBox.setText("测试时显示Chrome浏览器")
        self.selectChromeBtn.setText("浏览")
        self.chromeLabel.setText("Chrome浏览器路径")
        self.infoLabel.setText("未开始测试")
        self.pcapLabel.setText("Net Interface")
        self.corePathBtn.setText("浏览")
        self.radioWindow.setText("网页拖拽文件")
        # self.aiOptionBox.setText("AI")

        #init value
        self.saveDirLabel.hide()
        self.selectDirBtn.hide()

        self.gxpAction.setChecked(True)
        self.radioReboot.click()
        self.radioHttp.click()
        self.stopBtn.setEnabled(False)
        self.passwordLineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit)

        # set position-------------------------------
        xPos = 20
        yPos = 30
        colum2 = xPos +200

        # line 1
        self.ipLabel.move(xPos,yPos)
        self.intervalLabel.move(colum2,yPos)
        self.intervalSpinBox.move(colum2+60,yPos-2)
        self.ipLineEdit.move(xPos+50,yPos-2)

        # line 2
        line2 = yPos +40
        self.passwordLabel.move(xPos,line2)
        self.passwordLineEdit.move(xPos+50,line2-2)
        self.loopLabel.move(colum2,line2)
        self.loopSpinBox.move(colum2+60,line2-2)

        # line3
        line3 = yPos +80
        self.userLabel.move(xPos,line3)
        self.userLineEdit.move(xPos+50,line3-2)

        self.radioReboot.move(colum2,line3)
        self.radioFactory.move(colum2+60,line3)
        self.radioProvision.move(colum2,line3+30)

        self.webLabel.move(xPos,line3+40)
        self.webBtn.move(xPos+60,line3+35)

        # provWidget
        self.provWidget.resize(400,130)
        self.provWidget.move(xPos,line3+70)
        spaceY = 30
        x = 0
        y = 0
        cl = 200
        self.ver1Label.move(x,y)
        self.ver1LineEdit.move(x+50,y)
        self.ver2Label.move(x,y+spaceY)
        self.ver2LineEdit.move(x+50,y+spaceY)
        self.ver3Label.move(x,y+spaceY*2)
        self.ver3LineEdit.move(x+50,y+spaceY*2)

        self.dir1Label.move(cl,y)
        self.dir1LineEdit.move(cl+50,y)
        self.dir2Label.move(cl,y+spaceY)
        self.dir2LineEdit.move(cl+50,y+spaceY)
        self.dir3Label.move(cl,y+spaceY*2)
        self.dir3LineEdit.move(cl+50,y+spaceY*2)

        self.radioHttp.move(x,y+spaceY*3)
        self.radioHttps.move(x+50,y+spaceY*3)
        self.radioTftp.move(x+110,y+spaceY*3)
        self.radioFtp.move(x+160,y+spaceY*3)
        self.radioFtps.move(x+210,y+spaceY*3)
        self.radioWindow.move(x+265,y+spaceY*3)

        # advance widget
        self.advanceWidget.resize(300,400)
        x = 20
        y = 20
        space = 30

        self.checkCoreBox.move(x,y)
        self.cleanCache.move(x,y+space)
        self.checkProgressBox.move(x,y+space*2)
        self.checkShowChromeBox.move(x,y+space*3)
        self.apiCheckBox.move(x,y+space*4)
        self.corePathBtn.move(x-2,y+space*5-8)
        self.corePathLabel.move(x+35,y+space*5-8)

        y += 40
        self.chromeLabel.move(x,y+space*4+10)
        self.selectChromeBtn.move(x-2,y+space*5)
        self.chromePathLabel.move(x+35,y+space*5+2)

        self.checkSaveLogBox.move(x,y+space*6+10)
        self.selectDirBtn.move(x-2,y+space*7)
        self.saveDirLabel.move(x+35,y+space*7+2)
        self.advanceOkBtn.move(x+170,y+space*10+10)
        self.interfaceMenu.move(x-5,y+space*8+10)
        self.pcapLabel.move(x,y+space*8-2)
        # self.aiOptionBox.move(x, y+space*9+8)
        # set size
        self.messageBox.resize(373,155)
        # self.widget.resize(410,400)
        self.loopSpinBox.resize(60,25)
        self.intervalSpinBox.resize(60,25)
        self.webBtn.resize(100,25)

        self.saveDirLabel.resize(185,22)
        self.selectDirBtn.resize(32,24)
        self.selectChromeBtn.resize(32,24)
        self.chromePathLabel.resize(185,22)
        self.infoLabel.resize(400, 25)
        self.corePathBtn.resize(32,24)
        self.corePathLabel.resize(185,22)
        #
        self.provWidget.hide()
        self.changePosition(True)
        self.widget.show()
        self.loadCache()
    # ----------------end of setupUI ---------------------


    def changePosition(self,hide):
        xPos = 20
        if hide:
            buttonLine = 200
            self.widget.resize(420,415)
        else:
            buttonLine = 310
            self.widget.resize(420,524)

        self.startBtn.move(xPos,buttonLine)
        self.stopBtn.move(xPos+90,buttonLine)
        self.clearBtn.move(xPos+180,buttonLine)
        self.advanceBtn.move(xPos+270,buttonLine)
        self.messageBox.move(xPos,buttonLine+30)
        boxH = self.messageBox.height()
        self.infoLabel.move(xPos,buttonLine+boxH+35)

    def setItemEnable(self,enable):
        self.provWidget.setEnabled(enable)
        self.ipLineEdit.setEnabled(enable)
        self.passwordLineEdit.setEnabled(enable)
        self.userLineEdit.setEnabled(enable)
        self.intervalSpinBox.setEnabled(enable)
        self.loopSpinBox.setEnabled(enable)
        self.radioFactory.setEnabled(enable)
        self.radioReboot.setEnabled(enable)
        self.radioProvision.setEnabled(enable)
        self.advanceBtn.setEnabled(enable)
        self.startBtn.setEnabled(enable)
        self.clearBtn.setEnabled(enable)
        if self.useApiTest:
            self.webBtn.setEnabled(False)
        else:
            self.webBtn.setEnabled(enable)
        self.stopBtn.setEnabled(not enable)

    def outputError(self,str):
        appstr = "<span style=\"color:red\">"
        appstr += str + "</span>"
        self.messageBox.append(appstr)

    def outputWarning(self,str):
        appstr = "<span style=\"color:orange\">"
        appstr += str + "</span>"
        self.messageBox.append(appstr)

    def loadCache(self):
        file = QFile("cache")
        if not file.open(QIODevice.ReadOnly | QIODevice.Text):
            return

        inStream = QTextStream(file)

        # ip
        self.ipLineEdit.setText(inStream.readLine())
        # passwordLabel
        self.passwordLineEdit.setText(inStream.readLine())
        # user
        self.userLineEdit.setText(inStream.readLine())
        # ver1
        self.ver1LineEdit.setText(inStream.readLine())
        self.dir1LineEdit.setText(inStream.readLine())
        # ver2
        self.ver2LineEdit.setText(inStream.readLine())
        self.dir2LineEdit.setText(inStream.readLine())
        # ver3
        self.ver3LineEdit.setText(inStream.readLine())
        self.dir3LineEdit.setText(inStream.readLine())

        self.intervalSpinBox.setValue(int(inStream.readLine()))
        self.loopSpinBox.setValue(int(inStream.readLine()))

        # web type button
        webType = inStream.readLine()
        if webType == "gxpAction":
            self.grp2602Action.setChecked(False)
            self.gxpAction.setChecked(True)
            self.webBtn.setText(self.gxpAction.text())
        else:
            self.grp2602Action.setChecked(True)
            self.gxpAction.setChecked(False)
            self.webBtn.setText(self.grp2602Action.text())

        testType = inStream.readLine()
        if testType == "reboot":
            self.radioReboot.setChecked(True)
        elif testType == "provision":
            self.radioProvision.setChecked(True)
            self.changePosition(False)
            self.provWidget.show()
        else:
            self.radioFactory.setChecked(True)

        serverType = inStream.readLine()
        if serverType == "Http":
            self.radioHttp.setChecked(True)
        elif serverType == "Https":
            self.radioHttps.setChecked(True)
        elif serverType == "Tftp":
            self.radioTftp.setChecked(True)
        elif serverType == "Ftp":
            self.radioFtp.setChecked(True)
        elif serverType == "Ftps":            
            self.radioFtps.setChecked(True)
        else:
            self.radioWindow.setChecked(True)

        if inStream.readLine() == "True":
            self.findCoreStop = True
        else:
            self.findCoreStop = False

        if inStream.readLine() == "True":
            self.cleanCacheSet = True
        else:
            self.cleanCacheSet = False

        if inStream.readLine() == "True":
            self.useApiTest = True
            self.webBtn.setEnabled(False)
        else:
            self.useApiTest = False
            self.corePathBtn.hide()
            self.corePathLabel.hide()

        if inStream.readLine() == "True":
            self.showTestProgress = True
        else:
            self.showTestProgress = False
            self.infoLabel.hide()

        if inStream.readLine() == "True":
            self.showChrome = True
        else:
            self.showChrome = False

        self.chromePath = inStream.readLine()

        if inStream.readLine() == "True":
            self.saveTestLog = True
        else:
            self.saveTestLog = False

        self.saveLogPath = inStream.readLine()

        self.coreDumpPath = inStream.readLine()

        file.close()

    def saveCache(self):
        file = QFile("cache")
        if not file.open(QIODevice.WriteOnly):
            return

        content = self.ipLineEdit.text() + "\n"
        content += self.passwordLineEdit.text() + "\n"
        content += self.userLineEdit.text() + "\n"
        content += self.ver1LineEdit.text() + "\n"
        content += self.dir1LineEdit.text() + "\n"
        content += self.ver2LineEdit.text() + "\n"
        content += self.dir2LineEdit.text() + "\n"
        content += self.ver3LineEdit.text() + "\n"
        content += self.dir3LineEdit.text() + "\n"

        content += str(self.intervalSpinBox.value()) + "\n"
        content += str(self.loopSpinBox.value()) + "\n"

        if self.gxpAction.isChecked():
            content += "gxpAction\n"
        else:
            content += "grp2602Action\n"

        if self.radioReboot.isChecked():
            content += "reboot\n"
        elif self.radioProvision.isChecked():
            content += "provision\n"
        else:
            content += "factory\n"

        if self.radioHttp.isChecked():
            content += "Http\n"
        elif self.radioHttps.isChecked():
            content += "Https\n"
        elif self.radioTftp.isChecked():
            content += "Tftp\n"
        elif self.radioFtp.isChecked():
            content += "Ftp\n"
        elif self.radioFtps.isChecked():
            content += "Ftps\n"
        else :
            content += "Window\n"

        content += str(self.findCoreStop) + "\n"
        content += str(self.cleanCacheSet) + "\n"
        content += str(self.useApiTest) + "\n"
        content += str(self.showTestProgress) + "\n"
        content += str(self.showChrome) + "\n"
        content += self.chromePath +"\n"
        content += str(self.saveTestLog) +"\n"
        content += self.saveLogPath +"\n"
        content += self.coreDumpPath +"\n"

        byteArr = bytes(content,"utf-8")
        file.write(QByteArray(byteArr))
        file.close()


    def checkBeforeRun(self):
        containError = False
        #---------check Ip address--------------
        if self.ipLineEdit.text() == "":
            containError = True
            self.outputError("IP地址不能为空!")
        else:
            pattern = re.compile("^((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))$")
            if not pattern.search(self.ipLineEdit.text()):
                containError = True
                self.outputError("IP地址格式错误,检查是否含有多余空格!(仅支持IPV4)")

        #------------------------
        if self.passwordLineEdit.text() == "":
            containError = True
            self.outputError("密码不能为空!")
        if self.userLineEdit.text() == "":
            containError = True
            self.outputError("用户名不能为空!")
        if self.intervalSpinBox.value() <= 40:
            self.outputWarning("间隔时间过短,可能对测试造成影响")
        if not self.radioProvision.isChecked() and not self.radioReboot.isChecked() and \
           not self.radioFactory.isChecked():
            containError = True
            self.outputError("必须选择测试方式(重启,升降级,恢复出厂)")

        # check provision ----------
        if self.radioProvision.isChecked():
            if self.ver1LineEdit.text() == "" or self.ver2LineEdit.text() == "" or \
               self.dir1LineEdit.text() == "" or self.dir2LineEdit.text() == "":
                containError = True
                self.outputError("升降级测试至少填上前两个版本及其路径")

            bin_name = ""
            if os.path.exists(os.path.abspath("config.ini") ):
                f = open(os.path.abspath("config.ini") , "r")
                line = f.readline()
                while line:
                    option = line.split("=")
                    if option[0] == "firmbinname":
                        if option[1].strip('"') != "":
                            filenamebin = option[1].strip()
                            bin_name = filenamebin.strip('"')
                        pass
                    line = f.readline()
                f.close()

            filename = os.path.join(self.dir1LineEdit.text(), bin_name)
            if not os.path.exists(filename) and self.radioWindow.isChecked():
                containError = True
                self.outputError("firmware1 文件不存在!" + filename)
            filename = os.path.join(self.dir2LineEdit.text(), bin_name)
            if not os.path.exists(filename) and self.radioWindow.isChecked():
                containError = True
                self.outputError("firmware2 文件不存在!" + filename)
           

            filename = os.path.join(self.dir3LineEdit.text(), bin_name)
            if self.ver3LineEdit.text() != "" and self.dir3LineEdit.text() == "":
                containError = True
                self.outputError("填写了版本3,但对应路径为空!")
            if self.dir3LineEdit.text() != "" and self.ver3LineEdit.text() == "":
                containError = True
                self.outputError("填写了路径3,但对应版本为空!")
            elif self.dir3LineEdit.text() != "" and self.radioWindow.isChecked() and not os.path.exists(filename):
                containError = True
                self.outputError("firmware3 文件不存在!" + filename)

            if not self.radioFtp.isChecked() and not self.radioFtps.isChecked() and \
               not self.radioHttp.isChecked() and not self.radioHttps.isChecked() and \
               not self.radioTftp.isChecked() and not self.radioWindow.isChecked():
                containError = True
                self.outputError("升降级测试必须选择服务器类型(Tftp,Ftp,Ftps,Http,Https)")
        return containError



    def startTest(self):
        ip = self.ipLineEdit.text()
        passwd = self.passwordLineEdit.text()
        username = self.userLineEdit.text()
        ptime = self.intervalSpinBox.value()
        loop = self.loopSpinBox.value()
        modelType = self.webBtn.text()
        if self.gxpAction.isChecked():
            device_type = "GXP21XX"
        elif self.grp2602Action.isChecked():
            device_type = "GRP260X"

        if self.radioReboot.isChecked():
            task_type = "reboot"
        elif self.radioProvision.isChecked():
            task_type = "provision"
            text_ver1 = self.ver1LineEdit.text()
            text_ver2 = self.ver2LineEdit.text()
            text_ver3 = self.ver3LineEdit.text()
            text_dir1 = self.dir1LineEdit.text()
            text_dir2 = self.dir2LineEdit.text()
            text_dir3 = self.dir3LineEdit.text()
            prov_dict = {"ver1": text_ver1.strip(), "dir1": text_dir1.strip(), "ver2": text_ver2.strip(),
                        "dir2": text_dir2.strip(), "ver3": text_ver3.strip(), "dir3": text_dir3.strip()}

            if self.radioHttp.isChecked():
                self.man.update_prov_setting("HTTP", prov_dict)
            elif self.radioHttps.isChecked():
                self.man.update_prov_setting("HTTPS", prov_dict)
            elif self.radioTftp.isChecked():
                self.man.update_prov_setting("TFTP", prov_dict)
            elif self.radioFtp.isChecked():
                self.man.update_prov_setting("FTP", prov_dict)
            elif self.radioFtps.isChecked():
                self.man.update_prov_setting("FTPS", prov_dict)
            elif self.radioWindow.isChecked():
                self.man.update_prov_setting("browser", prov_dict)

        else:
            task_type = "reset"

        coredump_stop = True
        headless_flag = False
        clean_cache = False
        if self.checkCoreBox.isChecked() == False:
            self.messageBox.append("Find core dump will not stop")
            coredump_stop = False
        if self.cleanCache.isChecked() == True:
            clean_cache = True
            
        if self.checkShowChromeBox.isChecked() == True or self.radioWindow.isChecked() == True:
            headless_flag = False
        else:
            headless_flag = True

        # ai_mode = False
        # if self.aiOptionBox.isChecked() == True:
        #     ai_mode = True

        browser_path = ""
        if self.chromePathLabel.text() != "":
            browser_path = self.chromePathLabel.text()

        self.testStatus = [True,1,0,"ip",""]
        print(self.interfaceMenu.currentText())
        self.man.setStatus(self.testStatus)
        self.man.setMessageList(self.messageList)
        self.man.update_setting(ip.strip(), username.strip(), passwd.strip(), device_type, \
                                task_type, loop, ptime, coredump_stop, headless_flag, browser_path, \
                                clean_cache, self.interfaceMenu.currentText(), False)
    
    def startApiTest(self):
        ip = self.ipLineEdit.text()
        passwd = self.passwordLineEdit.text()
        username = self.userLineEdit.text()
        ptime = self.intervalSpinBox.value()
        loop = self.loopSpinBox.value()
        
        testType = "Reboot"
        if self.radioProvision.isChecked():
            testType = "Provision"
        self.api.setValue(ip,username,passwd,ptime,loop,testType)

        v1 = self.ver1LineEdit.text()
        v2 = self.ver2LineEdit.text()
        v3 = self.ver3LineEdit.text()
        d1 = self.dir1LineEdit.text()
        d2 = self.dir2LineEdit.text()
        d3 = self.dir3LineEdit.text()
        self.api.setVersion(v1,v2,v3,d1,d2,d3)

        self.api.setTestStatus(self.testStatus,self.messageList,self.coreDumpPath)

        if self.radioHttp.isChecked():
            self.api.setServerType("http")
        elif self.radioHttps.isChecked():
            self.api.setServerType("https")
        elif self.radioTftp.isChecked():
            self.api.setServerType("tftp")
        elif self.radioFtp.isChecked():
            self.api.setServerType("ftp")
        else: #self.radioFtps.isChecked()
            self.api.setServerType("ftps")
        
        self.api.setFoundCoreStop(self.findCoreStop)


    # slot ---------------------------------
    def apiTestBoxCheck(self,state):
        if state == 2:
            self.corePathBtn.show()
            self.corePathLabel.show()
        else:
            self.corePathBtn.hide()
            self.corePathLabel.hide()

    def clickedCorePathBtn(self):
        dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择Core Dump存放路径","/home")
        if dir != "":
            self.corePathLabel.setText(dir)
            self.coreDumpPath = dir

    def clickedSelectDirBtn(self):
        dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择日志存放路径","/home")
        if dir != "":
            self.saveDirLabel.setText(dir)
            self.saveLogPath = dir

    def clickedSelectChromeBtn(self):
        fileName = QFileDialog.getOpenFileName(self.advanceWidget,"选择谷歌浏览器","/home","Chrome (*.exe)")
        if fileName != "":
            self.chromePathLabel.setText(fileName[0])
            self.chromePath = fileName[0]

    def saveLogBoxCheck(self,state):
        if state == 2: # checked
            self.selectDirBtn.show()
            self.saveDirLabel.show()
        else:
            self.selectDirBtn.hide()
            self.saveDirLabel.hide()

    def clickedAdvanceOkBtn(self):
        self.findCoreStop = self.checkCoreBox.isChecked()
        self.cleanCacheSet = self.cleanCache.isChecked()
        self.useApiTest = self.apiCheckBox.isChecked()
        self.showTestProgress = self.checkProgressBox.isChecked()
        self.saveTestLog = self.checkSaveLogBox.isChecked()
        self.saveLogPath = self.saveDirLabel.text()
        self.showChrome = self.checkShowChromeBox.isChecked()
        self.chromePath = self.chromePathLabel.text()
        self.coreDumpPath = self.corePathLabel.text()

        if self.useApiTest:
            self.webBtn.setEnabled(False)
            self.corePathBtn.show()
            self.corePathLabel.show()
        else:
            self.webBtn.setEnabled(True)
            self.corePathBtn.hide()
            self.corePathLabel.hide()

        if self.showTestProgress:
            self.infoLabel.show()
        else:
            self.infoLabel.hide()
                
        self.saveCache()
        self.advanceWidget.hide()


    def clickedAdvanceBtn(self):
        self.advanceWidget.hide()
        self.checkCoreBox.setChecked(self.findCoreStop)
        self.cleanCache.setChecked(self.cleanCacheSet)
        self.apiCheckBox.setChecked(self.useApiTest)
        self.checkProgressBox.setChecked(self.showTestProgress)
        self.checkSaveLogBox.setChecked(self.saveTestLog)
        self.saveDirLabel.setText(self.saveLogPath)
        self.checkShowChromeBox.setChecked(self.showChrome)
        self.chromePathLabel.setText(self.chromePath)
        self.corePathLabel.setText(self.coreDumpPath)
        self.advanceWidget.show()

    def slotTestStoped(self):
        self.testStatus[0] = False
        self.setItemEnable(True)
        self.timer.stop()
        self.updateMessage()
        self.thread.quit()

        # save Test log
        if self.saveTestLog:
            fileName = time.strftime("%Y_%m_%d.%H_%M_%S.",time.localtime())
            if self.radioReboot.isChecked():
                fileName += "reboot"
            elif self.radioProvision:
                fileName += "provision"
            else:
                fileName += "factoryReset"
            fileName += ".htm"
            if self.saveLogPath == "":
                self.outputWarning("日志地址没有设置,无法保存")
            else:
                fileName = self.saveLogPath + "\\" + fileName
                print(fileName)

                file = QFile(fileName)
                if not file.open(QIODevice.WriteOnly):
                    self.outputError("打开文件错误,保存日志失败")
                    return

                byteArr = bytes(self.messageBox.toHtml(),"utf-8")
                file.write(QByteArray(byteArr))
                file.close()

    def clickedClearBtn(self):
        self.ipLineEdit.setText("")
        self.passwordLineEdit.setText("")
        self.userLineEdit.setText("")
        self.ver1LineEdit.setText("")
        self.dir1LineEdit.setText("")
        self.ver2LineEdit.setText("")
        self.dir2LineEdit.setText("")
        self.ver3LineEdit.setText("")
        self.dir3LineEdit.setText("")

    def clickedStarBtn(self):
        if self.checkBeforeRun():
            return
        self.messageBox.clear()
        self.saveCache()
        self.messageBox.append("Init Setting...")
        self.setItemEnable(False)
        self.timer.start(500)
        self.thread.start()

        # deside use what to test
        if self.useApiTest:
            if self.radioFactory.isChecked():
                self.outputWarning("Api not support Factory Reset, will test as Gxp type web driver")	
                self.clickedGxpType()
                self.startTest()
                self.signalRun.emit(self.man)
            else:
                self.startApiTest()
                self.signalRunApi.emit(self.api)
        else:
            self.startTest()
            self.signalRun.emit(self.man)

    def clickedStopBtn(self):
        self.stopBtn.setEnabled(False)
        self.testStatus[0] = False
        self.man.quit()
        self.outputWarning("正在停止...")

    def clickedProvision(self):
        self.provWidget.show()
        self.changePosition(False)

    def clickedOthers(self):
        self.provWidget.hide()
        self.changePosition(True)

    def clickedGxpType(self):
        self.gxpAction.setChecked(True)
        self.grp2602Action.setChecked(False)
        self.webBtn.setText(self.gxpAction.text())

    def clickedGrp2602(self):
        self.gxpAction.setChecked(False)
        self.grp2602Action.setChecked(True)
        self.webBtn.setText(self.grp2602Action.text())

    def updateMessage(self):
        while len(self.messageList) >0:
            info = self.messageList.popleft()
            self.messageBox.append(info)
        if self.testStatus[0] == False:
            self.infoLabel.setText("未开始测试")
        else:
            info = "第" + str(self.testStatus[1]) + "次测试   "
            if self.testStatus[2] > 0:
                info += "等待:{} 秒".format( self.testStatus[2] )
            else:
                info += "运行中"
            
            info += "  " + self.testStatus[3]
            info += "  " + self.testStatus[4]
            self.infoLabel.setText(info)
Beispiel #3
0
class MainWidget(QWidget):
    imA = 0
    imB = 1

    def __init__(self):
        QWidget.__init__(self)

        # Image arrays
        self.im_array_A = np.array([])
        self.im_array_B = np.array([])
        self.cur_im_arr = np.array([])

        self.w = 500
        self.h = 0
        self.ratio = 1

        self.active = None

        # Pixmap labels
        self.label_A = QLabel("Image A")
        self.pixmapA_label = QLabel()
        self.label_B = QLabel("Image B")
        self.pixmapB_label = QLabel()

        self.layout_A = QVBoxLayout()
        self.layout_A.addWidget(self.label_A)
        self.layout_A.addWidget(self.pixmapA_label)

        self.layout_B = QVBoxLayout()
        self.layout_B.addWidget(self.label_B)
        self.layout_B.addWidget(self.pixmapB_label)

        # Active image picker
        self.label_AB = QLabel("Select active image")
        self.label_AB.setMinimumWidth(500)
        self.radio_A = QRadioButton("A")
        self.radio_B = QRadioButton("B")
        self.radio_A.clicked.connect(self.set_active_A)
        self.radio_B.clicked.connect(self.set_active_B)
        self.layout_radio = QHBoxLayout()
        self.layout_radio.addWidget(self.radio_A)
        self.layout_radio.addWidget(self.radio_B)

        # Gaussian blur slider
        self.gauss_slider = QSlider()
        self.gauss_slider.setOrientation(Qt.Orientation.Horizontal)
        self.gauss_slider.setRange(0, 10)
        self.gauss_slider.valueChanged.connect(self.gaussian_blur)
        self.gauss_label = QLabel("Gaussian blur")
        self.gauss_button = QPushButton("Apply")
        self.gauss_button.clicked.connect(
            partial(self.apply_changes, "Gaussian blur"))

        self.gauss_layout = QHBoxLayout()
        self.gauss_layout.addWidget(self.gauss_slider)
        self.gauss_layout.addWidget(self.gauss_button)

        # Gamma slider
        self.gamma_slider = QSlider()
        self.gamma_slider.setOrientation(Qt.Orientation.Horizontal)
        self.gamma_slider.setRange(1, 9)
        self.gamma_slider.setValue(5)
        self.gamma_slider.valueChanged.connect(self.gamma_correction)
        self.gamma_label = QLabel("Gamma correction")
        self.gamma_button = QPushButton("Apply")
        self.gamma_button.clicked.connect(
            partial(self.apply_changes, "Gamma correction"))

        self.gamma_layout = QHBoxLayout()
        self.gamma_layout.addWidget(self.gamma_slider)
        self.gamma_layout.addWidget(self.gamma_button)

        # Equalize histogram button
        self.eq_hist_button = QPushButton("Equalize histogram")
        self.eq_hist_button.clicked.connect(self.equalize_histogram)

        # Median filter
        self.median_button = QPushButton("Median filter")
        self.median_button.clicked.connect(self.median_filter)

        # Find edges button
        self.edges_button = QPushButton("Find edges")
        self.edges_button.clicked.connect(self.find_edges)

        # Denoise button
        self.denoise_button = QPushButton("Denoise")
        self.denoise_button.clicked.connect(self.denoise)

        # Sharpen button
        self.sharpen_button = QPushButton("Sharpen")
        self.sharpen_button.clicked.connect(self.sharpen)

        # Colorize button
        self.colorize_button = QPushButton("Colorize")
        self.colorize_button.clicked.connect(self.colorize)

        # Flip image
        self.flip_button = QPushButton("Flip image")
        self.flip_button.clicked.connect(self.flip)

        # Undo button
        self.undo_button = QPushButton("Undo")
        self.undo_button.clicked.connect(self.undo)
        self.history_A = []
        self.history_B = []

        # Histogram
        self.canvas = FigureCanvasQTAgg(Figure(figsize=(4, 2)))
        self._static_ax = self.canvas.figure.subplots()
        self.hist_label = QLabel("Histogram")

        # Right layout
        self.layout_right = QVBoxLayout()
        self.layout_right.addWidget(self.label_AB)
        self.layout_right.addLayout(self.layout_radio)

        self.layout_right.addWidget(self.gauss_label)
        self.layout_right.addLayout(self.gauss_layout)

        self.layout_right.addWidget(self.gamma_label)
        self.layout_right.addLayout(self.gamma_layout)

        self.layout_right.addWidget(self.eq_hist_button)
        self.layout_right.addWidget(self.median_button)
        self.layout_right.addWidget(self.edges_button)
        self.layout_right.addWidget(self.denoise_button)
        self.layout_right.addWidget(self.sharpen_button)
        self.layout_right.addWidget(self.colorize_button)
        self.layout_right.addWidget(self.flip_button)

        self.layout_right.addStretch()

        self.layout_right.addWidget(self.undo_button)

        self.layout_right.addWidget(self.hist_label)
        self.layout_right.addWidget(self.canvas)

        # GUI layout
        self.layout = QHBoxLayout()
        self.layout.addLayout(self.layout_A)
        self.layout.addLayout(self.layout_B)
        self.layout.addLayout(self.layout_right)

        self.setLayout(self.layout)

    def new_file_received(self, fname):
        self.im_array_A, self.im_array_B = load_image(fname)
        self.history_A.clear()
        self.history_B.clear()

        self.gamma_slider.setValue(5)
        self.gauss_slider.setValue(0)

        self.ratio = self.im_array_A.shape[0] / self.im_array_A.shape[1]
        self.h = round(self.w * self.ratio)

        image_A = Image.fromarray(self.im_array_A)
        image_B = Image.fromarray(self.im_array_B)

        self.pixmapA_label.setPixmap(
            image_A.resize((self.w, self.h)).toqpixmap())
        self.pixmapB_label.setPixmap(
            image_B.resize((self.w, self.h)).toqpixmap())

        if self.active == self.imA:
            self.cur_im_arr = self.im_array_A
        elif self.active == self.imB:
            self.cur_im_arr = self.im_array_B

        self.radio_A.click()
        self.create_histogram()

    def save_image_A(self, fname):
        try:
            save_image(fname, self.im_array_A)
        except ValueError:
            dialog = QDialog(self)
            msg = "Invalid filename extension.\nPlease enter a valid image extension (such as .png or .jpg)"
            label = QLabel(msg)
            layout = QHBoxLayout()
            layout.addWidget(label)
            dialog.setLayout(layout)
            dialog.show()

    def save_image_B(self, fname):
        try:
            save_image(fname, self.im_array_B)
        except ValueError:
            dialog = QDialog(self)
            msg = "Invalid filename extension.\nPlease enter a valid image extension (such as .png or .jpg)"
            label = QLabel(msg)
            layout = QHBoxLayout()
            layout.addWidget(label)
            dialog.setLayout(layout)
            dialog.show()

    def save_image_AB(self, fname):
        im_array = np.concatenate((self.im_array_A, self.im_array_B), axis=1)
        try:
            save_image(fname, im_array)
        except ValueError:
            dialog = QDialog(self)
            msg = "Invalid filename extension.\nPlease enter a valid image extension (such as .png or .jpg)"
            label = QLabel(msg)
            layout = QHBoxLayout()
            layout.addWidget(label)
            dialog.setLayout(layout)
            dialog.show()

    @Slot()
    def set_active_A(self):
        self.active = self.imA
        self.cur_im_arr = self.im_array_A
        self.gamma_slider.setValue(5)
        self.gauss_slider.setValue(0)
        self.create_histogram()

    @Slot()
    def set_active_B(self):
        self.active = self.imB
        self.cur_im_arr = self.im_array_B
        self.gamma_slider.setValue(5)
        self.gauss_slider.setValue(0)
        self.create_histogram()

    @Slot()
    def gaussian_blur(self):
        self.gamma_slider.setValue(5)
        value = self.gauss_slider.value() / 5
        if self.active == self.imA:
            self.cur_im_arr = gaussian_blur(self.im_array_A, value)
        if self.active == self.imB:
            self.cur_im_arr = gaussian_blur(self.im_array_B, value)

        self.refresh_pixmap(self.cur_im_arr)
        self.gauss_label.setText(f"Gaussian blur: {value}")
        # self.create_histogram()

    @Slot()
    def gamma_correction(self):
        self.gauss_slider.setValue(0)
        value = self.gamma_slider.value() / 5
        if self.active == self.imA:
            self.cur_im_arr = gamma_correction(self.im_array_A, value)
        if self.active == self.imB:
            self.cur_im_arr = gamma_correction(self.im_array_B, value)

        self.refresh_pixmap(self.cur_im_arr)
        self.gamma_label.setText(f"Gamma correction: {value}")
        # self.create_histogram()

    @Slot()
    def equalize_histogram(self):
        if self.active == self.imA:
            self.cur_im_arr = equalize_histogram(self.im_array_A)
        if self.active == self.imB:
            self.cur_im_arr = equalize_histogram(self.im_array_B)

        self.refresh_pixmap(self.cur_im_arr)
        self.apply_changes("Histogram equalization")

    @Slot()
    def median_filter(self):
        if self.active == self.imA:
            self.cur_im_arr = median_filter(self.im_array_A)
        if self.active == self.imB:
            self.cur_im_arr = median_filter(self.im_array_B)

        self.refresh_pixmap(self.cur_im_arr)
        self.apply_changes("Median filter")

    @Slot()
    def find_edges(self):
        if self.active == self.imA:
            self.cur_im_arr = find_edges_scharr(self.im_array_A)
        if self.active == self.imB:
            self.cur_im_arr = find_edges_scharr(self.im_array_B)

        self.refresh_pixmap(self.cur_im_arr)
        self.apply_changes("Edge detection")

    @Slot()
    def denoise(self):
        if self.active == self.imA:
            self.cur_im_arr = denoise_tv(self.im_array_A)
        if self.active == self.imB:
            self.cur_im_arr = denoise_tv(self.im_array_B)

        self.refresh_pixmap(self.cur_im_arr)
        self.apply_changes("Denoise")

    @Slot()
    def sharpen(self):
        if self.active == self.imA:
            self.cur_im_arr = sharpen_mask(self.im_array_A)
        if self.active == self.imB:
            self.cur_im_arr = sharpen_mask(self.im_array_B)
        self.refresh_pixmap(self.cur_im_arr)
        self.apply_changes("Sharpen")

    @Slot()
    def colorize(self):
        color_im_arr = false_color(self.im_array_A, self.im_array_B)
        color_im = Image.fromarray(color_im_arr).resize((self.w, self.h))

        color_im_label = QLabel()
        color_im_label.setPixmap(color_im.toqpixmap())

        color_im_dialog = QDialog(self)
        color_im_dialog.setWindowTitle("Colorized image")

        save_button = QPushButton("Save")
        save_button.clicked.connect(partial(self.save_colorized, color_im_arr))

        layout = QVBoxLayout()
        layout.addWidget(color_im_label)
        layout.addWidget(save_button)

        color_im_dialog.setLayout(layout)
        color_im_dialog.show()

    @Slot()
    def save_colorized(self, im_arr):
        # Create file picker dialog
        dialog = QFileDialog(self)
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        # Get file name
        file_name = dialog.getSaveFileName()[0]
        if file_name == "": return

        save_image(file_name, im_arr)

    @Slot()
    def flip(self):
        if self.active == self.imA:
            self.cur_im_arr = np.flip(np.flip(self.im_array_A, axis=0), axis=1)
            self.refresh_pixmap(self.cur_im_arr)
            self.apply_changes("Flipped image A")
        if self.active == self.imB:
            self.cur_im_arr = np.flip(np.flip(self.im_array_B, axis=0), axis=1)
            self.refresh_pixmap(self.cur_im_arr)
            self.apply_changes("Flipped image B")

    @Slot()
    def apply_changes(self, message):
        if self.active == self.imA:
            if len(self.history_A) > 10:
                self.history_A.pop(0)
            self.history_A.append(self.im_array_A)
            self.im_array_A = self.cur_im_arr
        if self.active == self.imB:
            if len(self.history_B) > 10:
                self.history_B.pop(0)
            self.history_B.append(self.im_array_B)
            self.im_array_B = self.cur_im_arr
        self.create_histogram()

        self.gamma_slider.setValue(5)
        self.gauss_slider.setValue(0)

        self.parentWidget().status.showMessage(message)

    @Slot()
    def undo(self):
        if self.active == self.imA:
            if len(self.history_A) == 0: return
            self.im_array_A = self.history_A.pop()
            self.refresh_pixmap(self.im_array_A)
        if self.active == self.imB:
            if len(self.history_B) == 0: return
            self.im_array_B = self.history_B.pop()
            self.refresh_pixmap(self.im_array_B)

        self.create_histogram()

    def refresh_pixmap(self, im_arr):
        image = Image.fromarray(im_arr)
        if self.active == self.imA:
            self.pixmapA_label.setPixmap(
                image.resize((self.w, self.h)).toqpixmap())
        if self.active == self.imB:
            self.pixmapB_label.setPixmap(
                image.resize((self.w, self.h)).toqpixmap())

    def create_histogram(self):
        if self.active == self.imA:
            histogram = compute_histogram(self.im_array_A)
        if self.active == self.imB:
            histogram = compute_histogram(self.im_array_B)
        self._static_ax.clear()
        bins = histogram[1]
        vals = histogram[0]  # / np.sum(histogram[0])
        self._static_ax.bar(bins, vals)
        self._static_ax.set_yticklabels([])
        self._static_ax.figure.canvas.draw()
Beispiel #4
0
class PetrophysicsOptions(QWidget):
    polymorphic_states = {
        'DParsons': {'param1': 'Coeficiente de Dykstra-Parsons', 'param2': 'Grau de heterogenêidade', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)'], 'prop2': ['Permeabilidade (mD)'], 'prop3': '', 'prop4': ''},
        'Winland': {'param1': 'Garganta de Poro (Winland R35)', 'param2': '', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)', 'Porosidade (%)'], 'prop2': 'Porosidade (%)', 'prop3': '', 'prop4': ''},
        'Lucia': {'param1': 'Classificação de Lucia (Gráfico de classes carbonáticas)', 'param2': '', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade (mD)', 'Porosidade Interpartícula (%)'], 'prop2': '', 'prop3': '', 'prop4': ''},
        'RQIFZI':  {'param1': 'RQI (μm)', 'param2': 'FZI (gráfico)', 'param3': '', 'param4': '', 'prop1': ['Permeabilidade', 'Porosidade (%)'], 'prop2': ['Permeabilidade', 'Porosidade (%)'], 'prop3': [], 'prop4': []},
        'TCoates':  {'param1': 'FFI', 'param2': 'BVI', 'param3': 'Permeabilidade (mD)', 'param4': 'Swir (%)', 'prop1': ['Swir (%)', 'Porosidade (%)'], 'prop2': ['Swir (%)', 'Porosidade (%)'], 'prop3': ['Swir (%)', 'Porosidade (%)'], 'prop4': ['Permeabilidade (mD)', 'Porosidade (%)']},
        'KCarman': {'param1': 'Permeabilidade (mD)', 'param2': 'SVgr (cm-1)', 'param3': '', 'param4': '', 'prop1': ['Porosidade (%)', 'SVgr (cm-1)'], 'prop2': ['Permeabilidade (mD)', 'Porosidade (%)'], 'prop3': ['Permeabilidade (cm²)', 'Porosidade (decimal)'], 'prop4': []}
    }
    ready2calculate = Signal(bool)

    def __init__(self, _mode='KCarman'):
        super().__init__()

        self.mode = _mode

        self.subtitle = QLabel('Calcular:')

        self.label1 = QLabel()
        self.label2 = QLabel()
        self.label3 = QLabel()
        self.label4 = QLabel()

        self.labels = [self.label1, self.label2, self.label3, self.label4]

        for l in self.labels:
            l.setWordWrap(True)

        self.param1 = QRadioButton()
        self.param2 = QRadioButton()
        self.param3 = QRadioButton()
        self.param4 = QRadioButton()

        self.x_column = QLineEdit()
        self.y_column = QLineEdit()
        self.z_column = QLineEdit()
        self.destination_column = QLineEdit()

        self.results_l = QLabel('Resultados da análise: ')
        self.results = QTextEdit()

        self.unit_selector = Dropdown.Dropdown(['Darcy', 'SI'])

        self.run = QPushButton('Começar Análise')

        self.connections()
        self.changeMode(_mode)
        self.buildLayout()

        self.property_to_calculate = self.property_to_calculate = self.polymorphic_states[self.mode]['param1']
        self.payload = {}

        stly_sheet = "QRadioButton::indicator {width: 13px; height: 13px;} QRadioButton::indicator::unchecked {image: url(:/images/radiobutton_unchecked.png)} QRadioButton::indicator:unchecked:hover {image: url(:/images/radiobutton_unchecked_hover.png);}"

        self.subtitle.setStyleSheet('color: white')
        self.label1.setStyleSheet('color: white')
        self.label2.setStyleSheet('color: white')
        self.label3.setStyleSheet('color: white')
        self.label4.setStyleSheet('color: white')
        self.param1.setStyleSheet('color: white')
        self.param2.setStyleSheet('color: white')
        self.param3.setStyleSheet('color: white')
        self.param4.setStyleSheet('color: white')
        self.x_column.setStyleSheet('background-color: white; color: black')
        self.y_column.setStyleSheet('background-color: white; color: black')
        self.z_column.setStyleSheet('background-color: white; color: black')
        self.results.setStyleSheet('background-color: white; color: black')
        self.setStyleSheet('color:white; font-family: Bahnschrift SemiLight Condensed; font-size: 14px;')


    def buildLayout(self):
        layout = QFormLayout()

        a = self.polymorphic_states[self.mode]['prop1']
        b = self.polymorphic_states[self.mode]['prop2']
        c = self.polymorphic_states[self.mode]['prop3']
        d = self.polymorphic_states[self.mode]['prop4']

        layout.addWidget(self.subtitle)

        if len(self.param1.text()) != 0:
            layout.addWidget(self.param1)
        if len(self.param2.text()) != 0:
            layout.addWidget(self.param2)
        if len(self.param3.text()) != 0:
            layout.addWidget(self.param3)
        if len(self.param4.text()) != 0:
            layout.addWidget(self.param4)

        if len(self.label1.text()) != 0:
            layout.addWidget(self.label1)
            layout.addWidget(self.x_column)
        if len(self.label2.text()) != 0:
            layout.addWidget(self.label2)
            layout.addWidget(self.y_column)
        if len(self.label3.text()) != 0:
            layout.addWidget(self.label3)
            layout.addWidget(self.z_column)
        #if len(self.label4.text()) != 0:
            #layout.addWidget(self.label4)
            #layout.addWidget(self.destination_column)

        if self.mode == 'RQIFZI':
            layout.addWidget(QLabel('Sistema de Unidades: '))
            layout.addWidget(self.unit_selector)

        layout.addWidget(self.run)

        if self.mode == 'DParsons':
            layout.addWidget(self.results_l)
            layout.addWidget(self.results)
        if self.mode == 'Lucia':
            layout.addWidget(self.results_l)
            layout.addWidget(self.results)

        self.setLayout(layout)

    def connections(self):
        self.param1.clicked.connect(self.param1Active)
        self.param2.clicked.connect(self.param2Active)
        self.param3.clicked.connect(self.param3Active)
        self.param4.clicked.connect(self.param4Active)
        self.run.clicked.connect(self.collectPayload)

    def changeMode(self, _mode):
        self.mode = _mode
        self.param1.setText(self.polymorphic_states[self.mode]['param1'])
        self.param1.click()
        self.param2.setText(self.polymorphic_states[self.mode]['param2'])
        self.param3.setText(self.polymorphic_states[self.mode]['param3'])
        self.param4.setText(self.polymorphic_states[self.mode]['param4'])

    def param1Active(self):
        self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][0])
        try:
            self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][1])
        except IndexError:
            self.label2.setText('')
        try:
            self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop1'][2])
        except IndexError:
            self.label3.setText('')
        self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param1'])
        self.property_to_calculate = self.polymorphic_states[self.mode]['param1']

    def param2Active(self):
        self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][0])
        try:
            self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][1])
        except IndexError:
            self.label2.setText('')
        try:
            self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop2'][2])
        except IndexError:
            self.label3.setText('')
        self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param2'])
        self.property_to_calculate = self.polymorphic_states[self.mode]['param2']

    def param3Active(self):
        self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][0])
        try:
            self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][1])
        except IndexError:
            self.label2.setText('')
        try:
            self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop3'][2])
        except IndexError:
            self.label3.setText('')
        self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param3'])
        self.property_to_calculate = self.polymorphic_states[self.mode]['param3']

    def param4Active(self):
        self.label1.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][0])
        try:
            self.label2.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][1])
        except IndexError:
            self.label2.setText('')
        try:
            self.label3.setText('Selecione a coluna com os valores de ' + self.polymorphic_states[self.mode]['prop4'][2])
        except IndexError:
            self.label3.setText('')
        self.label4.setText('Selecione a coluna para os valores de ' + self.polymorphic_states[self.mode]['param4'])
        self.property_to_calculate = self.polymorphic_states[self.mode]['param4']

    def collectPayload(self):
        payload = {
            'calculate': self.property_to_calculate,
            'x_column': self.x_column.text(),
            'y_column': self.y_column.text(),
            'z_column': self.z_column.text(),
            'column_range': self.unit_selector.currentText(),
            'output_selection': None,
            'output_column': self.destination_column.text()
        }
        self.payload = payload
        print(payload)
        self.ready2calculate.emit(True)