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()
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)
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()
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)