class PythonWidget(QWidget): def __init__(self, parent): super().__init__(parent) self.pythonScript = QTextEdit() self.pythonScript.setReadOnly(False) # asked by Manolo self.pythonScript.setMaximumHeight(340) script_box = oasysgui.widgetBox(self, "", addSpace=False, orientation="vertical", height=545, width=750) script_box.layout().addWidget(self.pythonScript) console_box = oasysgui.widgetBox(script_box, "", addSpace=False, orientation="vertical", height=150, width=750) self.console = PythonConsole(self.__dict__, self) console_box.layout().addWidget(self.console) button_box = oasysgui.widgetBox(script_box, "", addSpace=False, orientation="horizontal") gui.button(button_box, self, "Run Script", callback=self.execute_script, height=35) gui.button(button_box, self, "Save Script to File", callback=self.save_script, height=35) def execute_script(self): self._script = str(self.pythonScript.toPlainText()) self.console.write("\nRunning script:\n") self.console.push("exec(_script)") self.console.new_prompt(sys.ps1) def save_script(self): file_name = QFileDialog.getSaveFileName(self, "Save File to Disk", ".", "*.py") if not file_name is None: if not file_name.strip() == "": file = open(file_name, "w") file.write(str(self.pythonScript.toPlainText())) file.close() QMessageBox.information(self, "QMessageBox.information()", "File " + file_name + " written to disk", QMessageBox.Ok) def setText(self, text): self.pythonScript.clear() self.pythonScript.setText(self.parse_nans(text)) def parse_nans(self, text): return text.replace("nan", "numpy.nan") # -------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------- if __name__ == "__main__": app = QApplication(sys.argv) w = OWmare() w.show() app.exec() w.saveSettings()
class SVNPluginPropsDialog( QDialog ): " SVN plugin properties dialog " def __init__( self, plugin, client, path, parent = None ): QDialog.__init__( self, parent ) self.__plugin = plugin self.__client = client self.__path = path self.__createLayout() self.setWindowTitle( "SVN Properties of " + path ) self.__populate() self.__propsView.setFocus() return def __populate( self ): " Populate the properties list " # Get the currently selected name selectedName = None selected = list( self.__propsView.selectedItems() ) if selected: selectedName = str( selected[ 0 ].text( 0 ) ) self.__propsView.clear() properties = readProperties( self.__client, self.__path ) if properties: for itemPath, itemProps in properties: if self.__path == itemPath or \ self.__path == itemPath + os.path.sep: for name, value in itemProps.iteritems(): name = str( name ).strip() value = str( value ).strip() newItem = QTreeWidgetItem( [ name, value ] ) self.__propsView.addTopLevelItem( newItem ) self.__resizePropsView() self.__sortPropsView() if selectedName: index = 0 for index in xrange( 0, self.__propsView.topLevelItemCount() ): item = self.__propsView.topLevelItem( index ) if selectedName == item.text( 0 ): item.setSelected( True ) return def __resizePropsView( self ): " Resizes the properties table " self.__propsView.header().setStretchLastSection( True ) self.__propsView.header().resizeSections( QHeaderView.ResizeToContents ) return def __sortPropsView( self ): " Sorts the properties table " self.__propsView.sortItems( self.__propsView.sortColumn(), self.__propsView.header().sortIndicatorOrder() ) return def __createLayout( self ): " Creates the dialog layout " self.resize( 640, 480 ) self.setSizeGripEnabled( True ) vboxLayout = QVBoxLayout( self ) hLayout = QHBoxLayout() self.__propsView = QTreeWidget() self.__propsView.setAlternatingRowColors( True ) self.__propsView.setRootIsDecorated( False ) self.__propsView.setItemsExpandable( False ) self.__propsView.setSortingEnabled( True ) self.__propsView.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.__propsView.itemSelectionChanged.connect( self.__propsSelectionChanged ) propsViewHeader = QTreeWidgetItem( [ "Property Name", "Property Value" ] ) self.__propsView.setHeaderItem( propsViewHeader ) self.__propsView.header().setSortIndicator( 0, Qt.DescendingOrder ) hLayout.addWidget( self.__propsView ) self.__delButton = QToolButton() self.__delButton.setText( "Delete" ) self.__delButton.setFocusPolicy( Qt.NoFocus ) self.__delButton.setEnabled( False ) self.__delButton.clicked.connect( self.__onDel ) hLayout.addWidget( self.__delButton, 0, Qt.AlignBottom ) vboxLayout.addLayout( hLayout ) # Set property part setGroupbox = QGroupBox( self ) setGroupbox.setTitle( "Set Property" ) setLayout = QGridLayout( setGroupbox ) setLayout.addWidget( QLabel( "Name" ), 0, 0, Qt.AlignTop | Qt.AlignRight ) setLayout.addWidget( QLabel( "Value" ), 1, 0, Qt.AlignTop | Qt.AlignRight ) self.__nameEdit = QLineEdit() self.__nameEdit.textChanged.connect( self.__nameChanged ) setLayout.addWidget( self.__nameEdit, 0, 1 ) self.__valueEdit = QTextEdit() self.__valueEdit.setAcceptRichText( False ) self.__valueEdit.textChanged.connect( self.__valueChanged ) metrics = QFontMetrics( self.__valueEdit.font() ) rect = metrics.boundingRect( "X" ) self.__valueEdit.setFixedHeight( rect.height() * 4 + 5 ) setLayout.addWidget( self.__valueEdit, 1, 1 ) self.__setButton = QToolButton() self.__setButton.setText( "Set" ) self.__setButton.setFocusPolicy( Qt.NoFocus ) self.__setButton.setEnabled( False ) self.__setButton.clicked.connect( self.__onSet ) setLayout.addWidget( self.__setButton, 1, 2, Qt.AlignBottom | Qt.AlignHCenter ) sizePolicy = QSizePolicy( QSizePolicy.Expanding, QSizePolicy.Maximum ) sizePolicy.setHorizontalStretch( 0 ) sizePolicy.setVerticalStretch( 0 ) sizePolicy.setHeightForWidth( setGroupbox.sizePolicy().hasHeightForWidth() ) setGroupbox.setSizePolicy( sizePolicy ) vboxLayout.addWidget( setGroupbox ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Ok ) buttonBox.button( QDialogButtonBox.Ok ).setDefault( True ) buttonBox.accepted.connect( self.close ) vboxLayout.addWidget( buttonBox ) return def __onSet( self ): " Triggered when propery set is clicked " name = self.__nameEdit.text().strip() value = self.__valueEdit.toPlainText().strip() try: commitInfo = self.__client.propset( name, value, self.__path ) if commitInfo: logging.info( str( commitInfo ) ) self.__populate() self.__plugin.notifyPathChanged( self.__path ) self.__nameEdit.clear() self.__valueEdit.clear() self.__propsView.setFocus() except pysvn.ClientError, exc: message = exc.args[ 0 ] logging.error( message ) return except Exception, exc: logging.error( str( exc ) ) return
class QChatWindow(QMainWindow): def __init__(self, client, messageQueue, isLightTheme): QMainWindow.__init__(self) self.client = client self.messageQueue = messageQueue self.isLightTheme = isLightTheme self.__setMenubar() self.chatLog = QTextEdit() self.chatLog.setReadOnly(True) self.chatInput = QTextEdit() self.chatInput.textChanged.connect(self.chatInputTextChanged) self.sendButton = QPushButton("Send") self.sendButton.clicked.connect(self.sendMessage) # Set the min height for the chatlog and a matching fixed height for the send button chatInputFontMetrics = QFontMetrics(self.chatInput.font()) self.chatInput.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3) self.sendButton.setFixedHeight(chatInputFontMetrics.lineSpacing() * 3) hboxLayout = QHBoxLayout() hboxLayout.addWidget(self.chatInput) hboxLayout.addWidget(self.sendButton) # Put the chatinput and send button in a wrapper widget so they may be added to the splitter chatInputWrapper = QWidget() chatInputWrapper.setLayout(hboxLayout) chatInputWrapper.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3.7) # Put the chat log and chat input into a splitter so the user can resize them at will splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.chatLog) splitter.addWidget(chatInputWrapper) splitter.setSizes([int(self.height()), 1]) vboxLayout = QVBoxLayout() vboxLayout.addWidget(splitter) # Add the completeted layout to the window self.centralWidget = QWidget() self.centralWidget.setLayout(vboxLayout) self.setCentralWidget(self.centralWidget) qtUtils.resizeWindow(self, 700, 400) qtUtils.centerWindow(self) # Title and icon self.setWindowTitle("Cryptully") self.setWindowIcon(QIcon(utils.getAbsoluteResourcePath('images/' + ('light' if isLightTheme else 'dark') + '/icon.png'))) self.statusBar().showMessage("Not Connected") def showNowChattingMessage(self): self.statusBar().showMessage("Connected to " + self.client.getHostname()) self.appendMessage("You are now securely chatting with " + self.client.getHostname() + " :)", constants.SERVICE, showTimestamp=False) self.appendMessage("It's a good idea to verify the communcation is secure by selecting" "\"verify key integrity\" in the options menu.", constants.SERVICE, showTimestamp=False) def chatInputTextChanged(self): if str(self.chatInput.toPlainText())[-1:] == '\n': self.sendMessage() def sendMessage(self): message = str(self.chatInput.toPlainText())[:-1] # Don't send empty messages if message == '': return # Add the message to the message queue to be sent self.messageQueue.put(message) # Clear the chat input self.chatInput.clear() self.appendMessage(message, constants.SENDER) @pyqtSlot(str, int, bool) def appendMessage(self, message, source, showTimestamp=True): if showTimestamp: timestamp = utils.getTimestamp() else: timestamp = '' color = self.__getColor(source) # If the user has scrolled up (current value != maximum), do not move the scrollbar # to the bottom after appending the message shouldScroll = True scrollbar = self.chatLog.verticalScrollBar() if scrollbar.value() != scrollbar.maximum() and source != constants.SENDER: shouldScroll = False # Append the message to the end of the chat log self.chatLog.append(timestamp + '<font color="' + color + '">' + message + "</font>") # Move the vertical scrollbar to the bottom of the chat log if shouldScroll: scrollbar.setValue(scrollbar.maximum()) def __getColor(self, source): if source == constants.SENDER: if self.isLightTheme: return '#0000CC' else: return '#6666FF' elif source == constants.RECEIVER: if self.isLightTheme: return '#CC0000' else: return '#CC3333' else: if self.isLightTheme: return '#000000' else: return '#FFFFFF' def __setMenubar(self): iconPath = 'images/' if self.isLightTheme: iconPath = iconPath + 'light/' else: iconPath = iconPath + 'dark/' fingerprintIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'fingerprint.png')) saveIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'save.png')) clearIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'delete.png')) helpIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'help.png')) exitIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'exit.png')) menuIcon = QIcon(utils.getAbsoluteResourcePath(iconPath + 'menu.png')) fingerprintAction = QAction(fingerprintIcon, '&Verify key integrity', self) saveKeypairAction = QAction(saveIcon, '&Save current encryption keys', self) clearKeypairAction = QAction(clearIcon, 'C&lear saved encryption keys', self) helpAction = QAction(helpIcon, 'Show &help', self) exitAction = QAction(exitIcon, '&Exit', self) fingerprintAction.triggered.connect(self.__showFingerprintDialog) saveKeypairAction.triggered.connect(self.__showSaveKeypairDialog) clearKeypairAction.triggered.connect(self.__clearKeypair) helpAction.triggered.connect(self.__showHelpDialog) exitAction.triggered.connect(self.__exit) fingerprintAction.setShortcut('Ctrl+I') saveKeypairAction.setShortcut('Ctrl+S') clearKeypairAction.setShortcut('Ctrl+L') helpAction.setShortcut('Ctrl+H') exitAction.setShortcut('Ctrl+Q') optionsMenu = QMenu() optionsMenu.addAction(fingerprintAction) optionsMenu.addAction(saveKeypairAction) optionsMenu.addAction(clearKeypairAction) optionsMenu.addAction(helpAction) optionsMenu.addAction(exitAction) toolButton = QToolButton() toolButton.setIcon(menuIcon) toolButton.setMenu(optionsMenu) toolButton.setPopupMode(QToolButton.InstantPopup) toolbar = self.addToolBar('toolbar') toolbar.addWidget(toolButton) def __showFingerprintDialog(self): QFingerprintDialog(self.client.sock.crypto).exec_() def __showSaveKeypairDialog(self): if utils.doesSavedKeypairExist(): QMessageBox.warning(self, "Keys Already Saved", "The current encryption keys have already been saved.") return QMessageBox.information(self, "Save Keys", "For extra security, your encryption keys will be protected with a passphrase. You'll need to enter this each time you start the app.") passphrase = qtUtils.getKeypairPassphrase(self.isLightTheme, parent=self, verify=True, showForgotButton=False) # Return if the user did not provide a passphrase if passphrase is None: return utils.saveKeypair(self.client.sock.crypto, passphrase) QMessageBox.information(QWidget(), "Keys Saved", "Encryption keys saved. The current keys will be used for all subsequent connections.") def __clearKeypair(self): qtUtils.clearKeypair(self) def __showHelpDialog(self): QHelpDialog(self).show() def __exit(self): qtUtils.exitApp()
class ErrorLogDialog(QDialog): def __init__(self, parent): super(ErrorLogDialog, self).__init__(parent, Qt.WindowStaysOnTopHint) self._empty = True self._initUI() self.setWindowTitle("Error") get_notification_center().connectLogMessage(self._checkLogMessage) for record in getCachedLogRecords(): self._checkLogMessage(record) def sizeHint(self): return QSize(400, 200) def _initUI(self): layout = QVBoxLayout(self) layout.setContentsMargins(0, 10, 0, 0) layout.setSpacing(0) labelLayout = QHBoxLayout() labelLayout.addWidget(QLabel(u"Sorry, something went wrong:", self)) labelLayout.setContentsMargins(10, 0, 0, 0) layout.addLayout(labelLayout) layout.addSpacing(5) self._errorLog = QTextEdit(self) self._errorLog.setReadOnly(True) self._errorLog.setWordWrapMode(QTextOption.NoWrap) self._errorLog.setTextColor(QColor(180, 0, 0)) self._errorLog.setObjectName(u"__ERROR_LOG_") self._errorLog.setFrameShape(QFrame.StyledPanel) if getPlatform() == PLATFORM_MAC: self._errorLog.setStyleSheet("QFrame#__ERROR_LOG_{border-width: 1px; border-top-style: solid; border-right-style: none; border-bottom-style: solid; border-left-style: none; border-color:palette(mid)}"); layout.addWidget(self._errorLog) bottomWidget = QWidget(self) bottomLayout = QHBoxLayout(bottomWidget) self._notAgain = QCheckBox(u"Please, no more error messages!", self) bottomLayout.addWidget(self._notAgain, 1, Qt.AlignTop) buttonBox = QDialogButtonBox(QDialogButtonBox.Close, Qt.Horizontal, self) buttonBox.rejected.connect(self.reject) bottomLayout.addWidget(buttonBox) layout.addWidget(bottomWidget) @loggingSlot() def reject(self): self._errorLog.clear() self._empty = True return QDialog.reject(self) @loggingSlot(object) def _checkLogMessage(self, record): try: if self._notAgain.checkState() == Qt.Checked: return if record.levelno >= logging.ERROR: recMsg = record.msg if not isinstance(recMsg, basestring): recMsg = unicode(recMsg) err = convert_string(recMsg) % record.args component = record.name if component.startswith("lunchinator."): component = component[12:] msg = u"%s - In component %s (%s:%d):\n%s" % (strftime("%H:%M:%S", localtime(record.created)), component, record.pathname, record.lineno, err) if record.exc_info: out = StringIO() traceback.print_tb(record.exc_info[2], file=out) msg += u"\nStack trace:\n" + out.getvalue() + formatException(record.exc_info) + u"\n" self._errorLog.append(msg) self._empty = False if not self.isVisible(): self.showNormal() self.raise_() self.activateWindow() except: from lunchinator.log import getCoreLogger getCoreLogger().info(formatException())
class ConsoleWidget(QWidget): _RECORD_ROLE = Qt.UserRole + 1 def __init__(self, parent, logger): super(ConsoleWidget, self).__init__(parent) self.logger = logger self._errorColor = QVariant(QColor(180, 0, 0)) self._warningColor = QVariant(QColor(170, 100, 0)) self._records = [] self._initModel() self._initUI() get_notification_center().connectLogMessage(self._addLogMessage) def _initUI(self): layout = QVBoxLayout(self) split = QSplitter(Qt.Vertical, self) layout.setContentsMargins(0, 0, 0, 0) console = QTreeView(self) console.setSortingEnabled(False) console.setHeaderHidden(False) console.setAlternatingRowColors(True) console.setIndentation(0) console.setUniformRowHeights(True) console.setObjectName(u"__console_log") console.setFrameShape(QFrame.StyledPanel) #if getPlatform() == PLATFORM_MAC: # console.setStyleSheet("QFrame#__console_log{border-width: 1px; border-top-style: none; border-right-style: none; border-bottom-style: solid; border-left-style: none; border-color:palette(mid)}"); console.setModel(self._logModel) console.header().setStretchLastSection(False) console.header().setResizeMode(3, QHeaderView.Stretch) console.selectionModel().selectionChanged.connect(self._selectionChanged) split.addWidget(console) detailsWidget = QWidget(self) detailsLayout = QVBoxLayout(detailsWidget) detailsLayout.setContentsMargins(0, 0, 0, 0) detailsLayout.setSpacing(0) detailsLayout.addWidget(QLabel(u"Details:", self)) self._detailsView = QTextEdit(self) self._detailsView.setReadOnly(True) self._detailsView.setWordWrapMode(QTextOption.NoWrap) detailsLayout.addWidget(self._detailsView, 1) split.addWidget(detailsWidget) layout.addWidget(split, 1) @loggingSlot(QItemSelection, QItemSelection) def _selectionChanged(self, newSel, _oldSel): if len(newSel.indexes()) == 0: self._detailsView.clear() else: index = newSel.indexes()[0] record = self._records[index.row()] try: logMsg = convert_string(record.msg) % record.args except: logMsg = convert_string(record.msg) + ', '.join(str(arg) for arg in record.args) msg = u"%s - In %s:%d: %s" % (strftime("%H:%M:%S", localtime(record.created)), record.pathname, record.lineno, logMsg) if record.exc_info: out = StringIO() traceback.print_tb(record.exc_info[2], file=out) msg += u"\nStack trace:\n" + out.getvalue() + formatException(record.exc_info) + u"\n" self._detailsView.setPlainText(msg) def _initModel(self): self._logModel = QStandardItemModel(self) self._logModel.setColumnCount(5) self._logModel.setHorizontalHeaderLabels([u"Time", u"Level", u"Component", u"Message", u"Source"]) for record in getCachedLogRecords(): self._addLogMessage(record) def _createItem(self, text, error, toolTip=None): item = QStandardItem() item.setEditable(False) item.setText(text) if error is 1: item.setData(self._warningColor, Qt.ForegroundRole) elif error is 2: item.setData(self._errorColor, Qt.ForegroundRole) if toolTip is None: toolTip = text item.setData(QVariant(toolTip), Qt.ToolTipRole) return item @loggingSlot(object) def _addLogMessage(self, record): self._records.append(record) msg = record.msg if not isinstance(msg, basestring): msg = unicode(msg) try: msg = convert_string(msg) % record.args except: msg = u"(Error formatting log message) " +\ convert_string(msg) +\ ', '.join(unicode(v) for v in record.args) dirname = os.path.dirname(record.pathname) source = u"%s:%d" % (os.path.join(os.path.basename(dirname), os.path.basename(record.pathname)), record.lineno) fullsource = u"%s:%d" % (record.pathname, record.lineno) component = record.name if component.startswith("lunchinator."): component = component[12:] error = 1 if record.levelno == logging.WARNING else 2 if record.levelno == logging.ERROR else 0 self._logModel.appendRow([self._createItem(strftime("%H:%M:%S", localtime(record.created)), error), self._createItem(record.levelname, error), self._createItem(component, error), self._createItem(msg, error), self._createItem(source, error, fullsource)])
class DUdpReplay(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Http replay dialog """ def __init__(self, parent=None, offlineMode=False): """ Constructor @param parent: @type parent: """ super(DUdpReplay, self).__init__(parent) self.offlineMode = offlineMode self.defaultIp = "127.0.0.1" self.defaultPort = "80" self.newTest = '' self.newTestExec = '' self.newInputs = [] self.requests = [] self.responses = [] self.defaultTemplates = DefaultTemplates.Templates() self.testType = None self.createDialog() self.createConnections() self.createActions() self.createToolbar() def createActions(self): """ Create qt actions """ self.openAction = QtHelper.createAction(self, "&Open", self.importTrace, icon=QIcon(":/folder_add.png"), tip='Open network trace.') self.exportTUAction = QtHelper.createAction( self, "&Test Unit", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to Test Unit') self.exportTSAction = QtHelper.createAction( self, "&Test Suite", self.exportToTS, icon=QIcon(":/%s.png" % WWorkspace.TestSuite.TYPE), tip='Export to Test Suite') self.cancelAction = QtHelper.createAction(self, "&Cancel", self.reject, tip='Cancel') menu = QMenu(self) menu.addAction(self.exportTUAction) menu.addAction(self.exportTSAction) self.exportToAction = QtHelper.createAction( self, "&Export to", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to tests') self.exportToAction.setMenu(menu) self.exportToAction.setEnabled(False) def createDialog(self): """ Create dialog """ self.dockToolbar = QToolBar(self) self.dockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.setWindowTitle(WINDOW_TITLE) self.resize(500, 400) self.ipEdit = QLineEdit(self.defaultIp) ipRegExpVal = QRegExpValidator(self) ipRegExp = QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") ipRegExpVal.setRegExp(ipRegExp) self.ipEdit.setValidator(ipRegExpVal) self.portEdit = QLineEdit(self.defaultPort) self.portEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) validatorPort = QIntValidator(self) self.portEdit.setValidator(validatorPort) self.progressBar = QProgressBar(self) self.progressBar.setMaximum(100) self.progressBar.setProperty("value", 0) self.progressBar.setAlignment(Qt.AlignCenter) self.progressBar.setObjectName("progressBar") self.guiSikuliGroupBox = QGroupBox("") self.guiSikuliGroupBox.setFlat(True) self.automaticAdp = QRadioButton("Automatic") self.automaticAdp.setChecked(True) self.defaultAdp = QRadioButton("Default") self.genericAdp = QRadioButton("Generic") vbox = QHBoxLayout() vbox.addWidget(self.automaticAdp) vbox.addWidget(self.defaultAdp) vbox.addWidget(self.genericAdp) vbox.addStretch(1) self.guiSikuliGroupBox.setLayout(vbox) layout = QVBoxLayout() layout.addWidget(self.dockToolbar) layout.addSpacing(12) paramLayout = QGridLayout() paramLayout.addWidget(QLabel("Destination IP:"), 0, 0, Qt.AlignRight) paramLayout.addWidget(self.ipEdit, 0, 1) paramLayout.addWidget(QLabel("Destination Port:"), 1, 0, Qt.AlignRight) paramLayout.addWidget(self.portEdit, 1, 1) paramLayout.addWidget(QLabel(self.tr("Gui adapter selector:")), 2, 0, Qt.AlignRight) paramLayout.addWidget(self.guiSikuliGroupBox, 2, 1) layout.addLayout(paramLayout) self.logsEdit = QTextEdit() self.logsEdit.setReadOnly(True) self.logsEdit.setTextInteractionFlags(Qt.NoTextInteraction) layout.addSpacing(12) layout.addWidget(self.logsEdit) layout.addSpacing(12) layout.addWidget(self.progressBar) self.setLayout(layout) def createToolbar(self): """ Create toolbar """ self.dockToolbar.setObjectName("File toolbar") self.dockToolbar.addAction(self.openAction) self.dockToolbar.addSeparator() self.dockToolbar.addAction(self.exportToAction) self.dockToolbar.addSeparator() self.dockToolbar.setIconSize(QSize(16, 16)) def createConnections(self): """ Create qt connections """ pass def autoScrollOnTextEdit(self): """ Automatic scroll on text edit """ cursor = self.logsEdit.textCursor() cursor.movePosition(QTextCursor.End) self.logsEdit.setTextCursor(cursor) def strip_html(self, txt): """ Strip html """ if "<" in txt: txt = txt.replace('<', '<') if ">" in txt: txt = txt.replace('>', '>') return txt def addLogSuccess(self, txt): """ Add log success in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkgreen'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogWarning(self, txt): """ Add log warning in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkorange'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogError(self, txt): """ Add log error in the text edit """ self.logsEdit.insertHtml("<span style='color:red'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLog(self, txt): """ Append log to the logsEdit widget """ self.logsEdit.insertHtml("%s<br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def importTrace(self): """ Import network trace """ self.logsEdit.clear() self.testType = None if not self.offlineMode: if not RCI.instance().isAuthenticated(): self.addLogWarning( txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return self.exportToAction.setEnabled(False) self.newTest = '' self.progressBar.setMaximum(100) self.progressBar.setValue(0) if sys.version_info > (3, ): fileName = QFileDialog.getOpenFileName( self, self.tr("Open File"), "", "Network dump (*.cap;*.pcap;*.pcapng)") else: fileName = QFileDialog.getOpenFileName(self, self.tr("Open File"), "", "Network dump (*.cap)") # new in v18 to support qt5 if QtHelper.IS_QT5: _fileName, _type = fileName else: _fileName = fileName # end of new if not _fileName: return if sys.version_info < (3, ): extension = str(_fileName).rsplit(".", 1)[1] if not (extension == "cap"): self.addLogError(txt="<< File not supported %s" % _fileName) QMessageBox.critical(self, "Open", "File not supported") return _fileName = str(_fileName) capName = _fileName.rsplit("/", 1)[1] self.addLogSuccess(txt=">> Reading the file %s" % _fileName) self.readFileV2(fileName=_fileName) def exportToTS(self): """ Export to test suite """ self.testType = TS self.exportToTest(TS=True, TU=False) def exportToTU(self): """ Export to test unit """ self.testType = TU self.exportToTest(TS=False, TU=True) def searchUDP(self): """ Search UDP module in assistant """ # modules accessor ret = "SutAdapters" if self.automaticAdp.isChecked(): isGeneric = WWorkspace.Helper.instance().isGuiGeneric(name="GUI") if isGeneric: ret = "SutAdapters.Generic" elif self.defaultAdp.isChecked(): return ret elif self.genericAdp.isChecked(): ret = "SutAdapters.Generic" else: pass return ret def exportToTest(self, TS=True, TU=False): """ Export to test """ if not RCI.instance().isAuthenticated(): self.addLogWarning(txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return if TS: self.newTest = self.defaultTemplates.getTestDefinitionAuto() self.newTestExec = self.defaultTemplates.getTestExecutionAuto() if TU: self.newTest = self.defaultTemplates.getTestUnitDefinitionAuto() destIp = str(self.ipEdit.text()) destPort = str(self.portEdit.text()) self.newInputs = [] self.newInputs.append({ 'type': 'self-ip', 'name': 'BIND_IP', 'description': '', 'value': '0.0.0.0', 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'BIND_PORT', 'description': '', 'value': '0', 'color': '' }) self.newInputs.append({ 'type': 'str', 'name': 'DEST_IP', 'description': '', 'value': '%s' % destIp, 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'DEST_PORT', 'description': '', 'value': '%s' % destPort, 'color': '' }) self.newInputs.append({ 'type': 'bool', 'name': 'DEBUG', 'description': '', 'value': 'False', 'color': '' }) self.newInputs.append({ 'type': 'float', 'name': 'TIMEOUT', 'description': '', 'value': '5.0', 'color': '' }) adps = """self.ADP_UDP = %s.UDP.Client(parent=self, bindIp=input('BIND_IP'), bindPort=input('BIND_PORT'), destinationIp=input('DEST_IP'), destinationPort=input('DEST_PORT'), debug=input('DEBUG'), separatorDisabled=True)""" % self.searchUDP( ) # prepare steps steps = [] j = 0 for i in xrange(len(self.requests)): j = i + 1 sentrecv, req = self.requests[i] if sentrecv == 'sent': steps.append( 'self.step%s = self.addStep(expected="udp data sent", description="send udp data", summary="send udp data")' % j) else: steps.append( 'self.step%s = self.addStep(expected="udp data received", description="received udp data", summary="received udp data")' % j) tests = [] for i in xrange(len(self.requests)): j = i + 1 sentrecv, req = self.requests[i] (source, dest, source_port, dest_port, data) = req if sentrecv == 'sent': tests.append("# data to sent %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): tests.append('rawSent = %s' % data.replace(b"'", b"\\'")) else: tests.append('rawSent = """%s"""' % data) tests.append('SentMsg = self.ADP_UDP.sendData(data=rawSent)') tests.append('if not SentMsg:') tests.append( '\tself.step%s.setFailed(actual="unable to send data")' % j) tests.append('else:') tests.append( '\tself.step%s.setPassed(actual="udp data sent succesfully")' % j) tests.append('') if sentrecv == 'recv': tests.append("# data to received %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): tests.append('rawRecv = %s' % data.replace(b'"', b'\\"')) else: tests.append('rawRecv = """%s"""' % data) tests.append( 'RecvMsg = self.ADP_UDP.hasReceivedData(data=rawRecv, timeout=input("TIMEOUT"))' ) tests.append('if RecvMsg is None:') tests.append( '\tself.step%s.setFailed(actual="unable to received data")' % j) tests.append('else:') tests.append( '\tself.step%s.setPassed(actual="udp data received succesfully")' % j) tests.append('') if TS: init = """self.ADP_UDP.startListening() udpListening = self.ADP_UDP.isListening( timeout=input('TIMEOUT') ) if not udpListening: self.abort( 'unable to listing to the udp port %s' ) """ % str(self.portEdit.text()) if TU: init = """self.ADP_UDP.startListening() udpListening = self.ADP_UDP.isListening( timeout=input('TIMEOUT') ) if not udpListening: self.abort( 'unable to connect to the udp port %s' ) """ % str(self.portEdit.text()) if TS: cleanup = """self.ADP_UDP.stopListening() udpStopped = self.ADP_UDP.isStopped( timeout=input('TIMEOUT') ) if not udpStopped: self.error( 'unable to no more listen from the udp port %s' ) """ % str(self.portEdit.text()) if TU: cleanup = """self.ADP_UDP.stopListening() udpStopped = self.ADP_UDP.isStopped( timeout=input('TIMEOUT') ) if not udpStopped: self.error( 'unable to no more listen from the udp port %s' ) """ % str(self.portEdit.text()) self.newTest = self.newTest.replace( "<<PURPOSE>>", 'self.setPurpose(purpose="Replay UDP")') self.newTest = self.newTest.replace("<<ADPS>>", adps) if TS: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t\t'.join(steps)) if TU: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t'.join(steps)) self.newTest = self.newTest.replace("<<INIT>>", init) self.newTest = self.newTest.replace("<<CLEANUP>>", cleanup) if TS: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t\t'.join(tests)) if TU: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t'.join(tests)) self.accept() def readFileV2(self, fileName): """ Read pcap file Support pcap-ng too """ fd = open(fileName, 'rb') fileFormat, fileHead = PcapParse.extractFormat(fd) if fileFormat == PcapParse.FileFormat.PCAP: self.trace("pcap file detected") pcapFile = PcapReader.PcapFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) elif fileFormat == PcapParse.FileFormat.PCAP_NG: self.trace("pcap-png file detected") pcapFile = PcapngReader.PcapngFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) else: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: file format = %s' % fileFormat) QMessageBox.critical(self, "Import", "File not supported") def readFilePacket(self, pcapFile): """ Read file packet by packet """ ip_expected = str(self.ipEdit.text()) port_expected = int(self.portEdit.text()) # read packet) packets = pcapFile() ethernetPackets = list(packets) self.addLogSuccess(txt="<< Total packets detected: %s " % len(ethernetPackets)) # extract udp packet according to the expected ip and port self.requests = [] i = 1 self.progressBar.setMaximum(len(ethernetPackets)) self.progressBar.setValue(0) for pkt in ethernetPackets: self.progressBar.setValue(i) i += 1 pktDecoded = PcapParse.decodePacket(pkt, getTcp=False, getUdp=True) if pktDecoded is not None: (source, dest, source_port, dest_port, data) = pktDecoded # skip when no data exists if dest == ip_expected and int(dest_port) == int( port_expected) and len(data) > 0: self.requests.append(('sent', pktDecoded)) if source == ip_expected and int(source_port) == int( port_expected) and len(data) > 0: self.requests.append(('recv', pktDecoded)) self.addLogSuccess(txt="<< Number of UDP packets detected: %s" % len(self.requests)) if self.requests: self.addLogSuccess("<< File decoded with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No udp extracted!")
class TermWidget(QWidget): """Widget wich represents terminal. It only displays text and allows to enter text. All highlevel logic should be implemented by client classes """ def __init__(self, font, *args): QWidget.__init__(self, *args) self._browser = QTextEdit(self) self._browser.setReadOnly(True) document = self._browser.document() document.setDefaultStyleSheet(document.defaultStyleSheet() + "span {white-space:pre;}") self._browser.setFont(font) self._edit = _TextEdit(self, font) lowLevelWidget = self._edit.focusProxy() if lowLevelWidget is None: lowLevelWidget = self._edit lowLevelWidget.installEventFilter(self) self._edit.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.setFocusProxy(self._edit) layout = QVBoxLayout(self) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._browser) layout.addWidget(self._edit) self._history = [''] # current empty line self._historyIndex = 0 self._edit.setFocus() def terminate(self): self._edit.terminate() def eventFilter(self, obj, event): pass # suppress docsting for non-public method """QWidget.eventFilter implementation. Catches _edit key pressings. Processes some of them """ if event.type() == QEvent.KeyPress: if event.matches(QKeySequence.MoveToNextLine): if self._edit.cursorPosition[0] == (len(self._edit.lines) - 1): self._onHistoryNext() return True elif event.matches(QKeySequence.MoveToPreviousLine): if self._edit.cursorPosition[0] == 0: self._onHistoryPrev() return True elif event.matches(QKeySequence.MoveToNextPage) or \ event.matches(QKeySequence.MoveToPreviousPage): self._browser.keyPressEvent(event) return True elif event.matches(QKeySequence.InsertParagraphSeparator): return self._editNewLineEvent() return QWidget.eventFilter(self, obj, event) def _appendToBrowser(self, style, text): """Convert text to HTML for inserting it to browser. Insert the HTML """ text = cgi.escape(text) text = text.replace('\n', '<br/>') defBg = self._browser.palette().color(QPalette.Base) h, s, v, a = defBg.getHsvF() if style == 'out': pass elif style == 'in': if v > 0.5: # white background v = v - (v / 8) # make darker else: v = v + ((1 - v) / 4) # make ligher elif style == 'err': if v < 0.5: # dark background v = v + ((1 - v) / 4) # make ligher h = 0 s = .4 elif style == 'hint': if v < 0.5: # dark background v = v + ((1 - v) / 4) # make ligher h = 0.33 s = .4 else: assert 0 bg = QColor.fromHsvF(h, s, v) text = '<span style="background-color: %s;">%s</span>' % (bg.name(), text) scrollBar = self._browser.verticalScrollBar() oldValue = scrollBar.value() if False: # hlamer: It seems, it is more comfortable, if text is always scrolled scrollAtTheEnd = oldValue == scrollBar.maximum() else: scrollAtTheEnd = True self._browser.moveCursor(QTextCursor.End) self._browser.insertHtml(text) if scrollAtTheEnd: scrollBar.setValue(scrollBar.maximum()) else: scrollBar.setValue(oldValue) while self._browser.document().characterCount() > 1024 * 1024: cursor = self._browser.cursorForPosition(QPoint(0, 0)) cursor.select(cursor.LineUnderCursor) if not cursor.selectedText(): cursor.movePosition(cursor.Down, cursor.KeepAnchor) cursor.movePosition(cursor.EndOfLine, cursor.KeepAnchor) cursor.removeSelectedText() def setLanguage(self, language): """Set highlighting language for input widget """ self._edit.detectSyntax(language=language) def execCommand(self, text): """Save current command in the history. Append it to the log. Execute child's method. Clear edit line. """ self._appendToBrowser('in', text + '\n') if len(self._history) < 2 or\ self._history[-2] != text: # don't insert duplicating items self._history.insert(-1, text) self._historyIndex = len(self._history) - 1 self._history[-1] = '' self._edit.text = '' if not text.endswith('\n'): text += '\n' self.childExecCommand(text) def childExecCommand(self, text): """Reimplement in the child classes to execute enterred commands """ pass def appendOutput(self, text): """Appent text to output widget """ self._appendToBrowser('out', text) def appendError(self, text): """Appent error text to output widget. Text is drawn with red background """ self._appendToBrowser('err', text) def appendHint(self, text): """Appent error text to output widget. Text is drawn with red background """ self._appendToBrowser('hint', text) def clear(self): """Clear the widget""" self._browser.clear() def isCommandComplete(self, text): """Executed when Enter is pressed to check if widget should execute the command, or insert newline. Implement this function in the child classes. """ return True def _editNewLineEvent(self): """Handler of Enter pressing in the edit """ text = self._edit.text if self.isCommandComplete(text): self.execCommand(text) return True # processing finished else: return False # let the editor process the event def _onHistoryNext(self): """Down pressed, show next item from the history """ if (self._historyIndex + 1) < len(self._history): self._historyIndex += 1 self._edit.text = self._history[self._historyIndex] self._edit.absCursorPosition = len(self._edit.text) def _onHistoryPrev(self): """Up pressed, show previous item from the history """ if self._historyIndex > 0: if self._historyIndex == (len(self._history) - 1): self._history[-1] = self._edit.text self._historyIndex -= 1 self._edit.text = self._history[self._historyIndex] self._edit.absCursorPosition = len(self._edit.text)
class HDFWidget(QWidget): def __init__(self, parent=None): super(HDFWidget, self).__init__(parent=parent) self.parent = parent self.main_layout = QVBoxLayout() ### Select Dataset and properties ### self.layout = QHBoxLayout() self.list = QListWidget() self.textBox = QTextEdit() self.textBox.resize(200, 200) ### Add button ### self.button = QPushButton("Apply") self.main_layout.addLayout(self.layout) self.main_layout.addWidget(self.button) self.setLayout(self.main_layout) self.layout.addWidget(self.list) self.layout.addWidget(self.textBox) ### Variables ### self.settings = None self.list.itemClicked.connect(self.item_clicked) self.connect(self.button, QtCore.SIGNAL("clicked()"), self.apply_settings) def item_clicked(self, item): """Action triggered when an item is clicked. The content of the metadata is retrieved from its index and not from the file itself, avoiding clashes with the main program. """ i = self.list.currentRow() self.settings = self.all_settings[i] self.textBox.clear() self.textBox.setText(self.settings) # mdd = self.settings.split('\n') # for t in mdd: # self.textBox.append(t) def add_items(self, name): """ Adds the group items to the display. The file is closed after extracting the metadata, to avoid conflicts with the main program. :param name: Name of the HDF file to be opened. :return: Null """ f = h5py.File(name, 'r') self.settings = None self.all_settings = [] self.list.clear() for g in f: self.all_settings.append(f[g + '/metadata'][()].decode('ascii')) self.list.addItem(g) f.close() def apply_settings(self): """ Triggered when the apply button is pressed. The settings are broadcasted as coming from the parent. """ if self.settings is not None: self.parent.emit(QtCore.SIGNAL('settings'), self.settings)
class QChatWidget(QWidget): def __init__(self, connectionManager, parent=None): QWidget.__init__(self, parent) self.connectionManager = connectionManager self.isDisabled = False self.wasCleared = False self.urlRegex = re.compile(constants.URL_REGEX) self.chatLog = QTextBrowser() self.chatLog.setOpenExternalLinks(True) self.chatInput = QTextEdit() self.chatInput.textChanged.connect(self.chatInputTextChanged) self.sendButton = QPushButton("Send") self.sendButton.clicked.connect(self.sendMessage) # Set the min height for the chatlog and a matching fixed height for the send button chatInputFontMetrics = QFontMetrics(self.chatInput.font()) self.chatInput.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3) self.sendButton.setFixedHeight(chatInputFontMetrics.lineSpacing() * 3) hbox = QHBoxLayout() hbox.addWidget(self.chatInput) hbox.addWidget(self.sendButton) # Put the chatinput and send button in a wrapper widget so they may be added to the splitter chatInputWrapper = QWidget() chatInputWrapper.setLayout(hbox) chatInputWrapper.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3.7) # Put the chat log and chat input into a splitter so the user can resize them at will splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.chatLog) splitter.addWidget(chatInputWrapper) splitter.setSizes([int(parent.height()), 1]) hbox = QHBoxLayout() hbox.addWidget(splitter) self.setLayout(hbox) self.typingTimer = QTimer() self.typingTimer.setSingleShot(True) self.typingTimer.timeout.connect(self.stoppedTyping) def chatInputTextChanged(self): # Check if the text changed was the text box being cleared to avoid sending an invalid typing status if self.wasCleared: self.wasCleared = False return if str(self.chatInput.toPlainText())[-1:] == '\n': self.sendMessage() else: # Start a timer to check for the user stopping typing self.typingTimer.start(constants.TYPING_TIMEOUT) self.sendTypingStatus(constants.TYPING_START) def stoppedTyping(self): self.typingTimer.stop() if str(self.chatInput.toPlainText()) == '': self.sendTypingStatus(constants.TYPING_STOP_WITHOUT_TEXT) else: self.sendTypingStatus(constants.TYPING_STOP_WITH_TEXT) def sendMessage(self): if self.isDisabled: return self.typingTimer.stop() text = str(self.chatInput.toPlainText())[:-1] # Don't send empty messages if text == '': return # Convert URLs into clickable links text = self.__linkify(text) # Add the message to the message queue to be sent self.connectionManager.getClient(self.nick).sendChatMessage(text) # Clear the chat input self.wasCleared = True self.chatInput.clear() self.appendMessage(text, constants.SENDER) def sendTypingStatus(self, status): self.connectionManager.getClient(self.nick).sendTypingMessage(status) def showNowChattingMessage(self, nick): self.nick = nick self.appendMessage("You are now securely chatting with " + self.nick + " :)", constants.SERVICE, showTimestampAndNick=False) self.appendMessage( "It's a good idea to verify the communcation is secure by selecting " "\"authenticate buddy\" in the options menu.", constants.SERVICE, showTimestampAndNick=False) def appendMessage(self, message, source, showTimestampAndNick=True): color = self.__getColor(source) if showTimestampAndNick: timestamp = '<font color="' + color + '">(' + utils.getTimestamp() + ') <strong>' + \ (self.connectionManager.nick if source == constants.SENDER else self.nick) + \ ':</strong></font> ' else: timestamp = '' # If the user has scrolled up (current value != maximum), do not move the scrollbar # to the bottom after appending the message shouldScroll = True scrollbar = self.chatLog.verticalScrollBar() if scrollbar.value() != scrollbar.maximum( ) and source != constants.SENDER: shouldScroll = False self.chatLog.append(timestamp + message) # Move the vertical scrollbar to the bottom of the chat log if shouldScroll: scrollbar.setValue(scrollbar.maximum()) def __linkify(self, text): matches = self.urlRegex.findall(text) for match in matches: text = text.replace(match[0], '<a href="%s">%s</a>' % (match[0], match[0])) return text def __getColor(self, source): if source == constants.SENDER: if qtUtils.isLightTheme: return '#0000CC' else: return '#6666FF' elif source == constants.RECEIVER: if qtUtils.isLightTheme: return '#CC0000' else: return '#CC3333' else: if qtUtils.isLightTheme: return '#000000' else: return '#FFFFFF' def disable(self): self.isDisabled = True self.chatInput.setReadOnly(True) def enable(self): self.isDisabled = False self.chatInput.setReadOnly(False)
class EditBox(QDialog): def __init__(self, data, title, description=None, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(title) self.setWindowModality(Qt.ApplicationModal) QVBoxLayout(self) self.list = ListEdit(parent=parent, isChild=True) self.list.displayUpDown = False self.list.editInPopup = False self.list.headers = parent.getHeaders() self.list.setColDelegate(parent.getColDelegate) self.list.reset([data]) self.info = QTextEdit() self.error = QTextEdit() self.grid = None self.build(description) def build(self, description): self.layout().addWidget(self.list) cancel = QPushButton(QIcon(":/icons/wrong.png"), tr("Cancel"), self) save = QPushButton(QIcon(":/icons/apply.png"), tr("OK"), self) save.setDefault(True) self.connect(cancel, SIGNAL("clicked()"), self.doClose) self.connect(save, SIGNAL("clicked()"), self.doSave) self.grid = QWidget(self) self.setMinimumWidth(700) QGridLayout(self.grid) self.grid.layout().addWidget(save, 0, 0, Qt.AlignHCenter) self.grid.layout().addWidget(cancel, 0, 1, Qt.AlignHCenter) self.layout().addWidget(self.grid) self.info.setReadOnly(True) if description: self.info.append(description) else: self.info.setVisible(False) self.error.setReadOnly(True) self.error.setVisible(False) self.grid.layout().addWidget(self.info, 1, 0, 1, 0, Qt.AlignHCenter) self.grid.layout().addWidget(self.error, 2, 0, 1, 0, Qt.AlignHCenter) def doClose(self): self.reject() self.close() def doSave(self): self.error.clear() hasInvalidData = False for col in range(self.list.listEditView.model.columnCount()): index = self.list.listEditView.model.index(0, col) input_edit = self.list.listEditView.indexWidget(index) if not input_edit.isValid(): col_name = self.list.listEditView.model.headerData(col, Qt.Horizontal, Qt.DisplayRole) col_name = unicode(col_name.toString()) self.error.append(tr("Column '%s': must be '%s'") % (col_name, input_edit.getFieldInfo())) hasInvalidData = True if hasInvalidData: self.error.setVisible(True) else: self.accept() self.close() def getData(self): """ single selection only supported """ return self.list.rawData()[0]
class QChatWidget(QWidget): def __init__(self, connectionManager, parent=None): QWidget.__init__(self, parent) self.connectionManager = connectionManager self.isDisabled = False self.wasCleared = False self.urlRegex = re.compile(constants.URL_REGEX) self.chatLog = QTextBrowser() self.chatLog.setOpenExternalLinks(True) self.chatInput = QTextEdit() self.chatInput.textChanged.connect(self.chatInputTextChanged) self.sendButton = QPushButton("Send") self.sendButton.clicked.connect(self.sendMessage) # Set the min height for the chatlog and a matching fixed height for the send button chatInputFontMetrics = QFontMetrics(self.chatInput.font()) self.chatInput.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3) self.sendButton.setFixedHeight(chatInputFontMetrics.lineSpacing() * 3) hbox = QHBoxLayout() hbox.addWidget(self.chatInput) hbox.addWidget(self.sendButton) # Put the chatinput and send button in a wrapper widget so they may be added to the splitter chatInputWrapper = QWidget() chatInputWrapper.setLayout(hbox) chatInputWrapper.setMinimumHeight(chatInputFontMetrics.lineSpacing() * 3.7) # Put the chat log and chat input into a splitter so the user can resize them at will splitter = QSplitter(Qt.Vertical) splitter.addWidget(self.chatLog) splitter.addWidget(chatInputWrapper) splitter.setSizes([int(parent.height()), 1]) hbox = QHBoxLayout() hbox.addWidget(splitter) self.setLayout(hbox) self.typingTimer = QTimer() self.typingTimer.setSingleShot(True) self.typingTimer.timeout.connect(self.stoppedTyping) def chatInputTextChanged(self): # Check if the text changed was the text box being cleared to avoid sending an invalid typing status if self.wasCleared: self.wasCleared = False return if str(self.chatInput.toPlainText())[-1:] == "\n": self.sendMessage() else: # Start a timer to check for the user stopping typing self.typingTimer.start(constants.TYPING_TIMEOUT) self.sendTypingStatus(constants.TYPING_START) def stoppedTyping(self): self.typingTimer.stop() if str(self.chatInput.toPlainText()) == "": self.sendTypingStatus(constants.TYPING_STOP_WITHOUT_TEXT) else: self.sendTypingStatus(constants.TYPING_STOP_WITH_TEXT) def sendMessage(self): if self.isDisabled: return self.typingTimer.stop() text = str(self.chatInput.toPlainText())[:-1] # Don't send empty messages if text == "": return # Convert URLs into clickable links text = self.__linkify(text) # Add the message to the message queue to be sent self.connectionManager.getClient(self.nick).sendChatMessage(text) # Clear the chat input self.wasCleared = True self.chatInput.clear() self.appendMessage(text, constants.SENDER) def sendTypingStatus(self, status): self.connectionManager.getClient(self.nick).sendTypingMessage(status) def showNowChattingMessage(self, nick): self.nick = nick self.appendMessage( "You are now securely chatting with " + self.nick + " :)", constants.SERVICE, showTimestampAndNick=False ) self.appendMessage( "It's a good idea to verify the communcation is secure by selecting " '"authenticate buddy" in the options menu.', constants.SERVICE, showTimestampAndNick=False, ) def appendMessage(self, message, source, showTimestampAndNick=True): color = self.__getColor(source) if showTimestampAndNick: timestamp = ( '<font color="' + color + '">(' + utils.getTimestamp() + ") <strong>" + (self.connectionManager.nick if source == constants.SENDER else self.nick) + ":</strong></font> " ) else: timestamp = "" # If the user has scrolled up (current value != maximum), do not move the scrollbar # to the bottom after appending the message shouldScroll = True scrollbar = self.chatLog.verticalScrollBar() if scrollbar.value() != scrollbar.maximum() and source != constants.SENDER: shouldScroll = False self.chatLog.append(timestamp + message) # Move the vertical scrollbar to the bottom of the chat log if shouldScroll: scrollbar.setValue(scrollbar.maximum()) def __linkify(self, text): matches = self.urlRegex.findall(text) for match in matches: text = text.replace(match[0], '<a href="%s">%s</a>' % (match[0], match[0])) return text def __getColor(self, source): if source == constants.SENDER: if qtUtils.isLightTheme: return "#0000CC" else: return "#6666FF" elif source == constants.RECEIVER: if qtUtils.isLightTheme: return "#CC0000" else: return "#CC3333" else: if qtUtils.isLightTheme: return "#000000" else: return "#FFFFFF" def disable(self): self.isDisabled = True self.chatInput.setReadOnly(True) def enable(self): self.isDisabled = False self.chatInput.setReadOnly(False)
class InteractiveVelocityPlot(VelocityPlot): """ Visual tool to help with fitting Voigt profiles to absorption lines in QSO spectra. """ def __init__(self, filename, transitions, wavelength, flux, error, continuum, redshift, **kwargs): # Main window: self.window = QMainWindow() # Host widget for plot, push button, and checkboxes: self.main_frame = QWidget() # Spectrum filename: self.filename = filename # Plotting options: self.options = kwargs # Optimise screen usage: if len(transitions) > 20: ncols = int(ceil(len(transitions) / 10)) else: ncols = int(ceil(len(transitions) / 5)) # Initialise plot: super(InteractiveVelocityPlot, self).__init__( transitions, ncols=ncols, aspect=0.45, **self.options['WINDOW']) # Attach canvas to host widget: self.canvas = FigureCanvasQTAgg(self) self.canvas.setParent(self.main_frame) # Text input/output: self.text_output = QTextEdit() # Push buttons: self.load_button = QPushButton('&Load') self.save_button = QPushButton('&Save') self.preview_button = QPushButton('&Preview') self.clear_button = QPushButton('&Clear') self.refresh_plot_button = QPushButton('&Refresh plot') self.plot_model_button = QPushButton('&Plot model') self.plot_all_models_button = QPushButton('&Plot all models') self.clear_models_button = QPushButton('&Clear models') self.runvpfit_button = QPushButton('&Run VPFIT') self.set_resolution = QPushButton('&Set resolution') self.help = QPushButton('&Help') self.quit = QPushButton('&Quit') # Checkboxes: self.cos_fuv_checkbox = QCheckBox('&use COS FUV LSF') self.cos_nuv_checkbox = QCheckBox('&use COS NUV LSF') self.include_checkbox = QCheckBox('&include previous') # Push button `clicked` connections: self.load_button.clicked.connect(self.on_load) self.save_button.clicked.connect(self.on_save) self.preview_button.clicked.connect(self.on_preview) self.clear_button.clicked.connect(self.on_clear) self.refresh_plot_button.clicked.connect(self.on_refresh) self.plot_model_button.clicked.connect(self.on_plot_model) self.plot_all_models_button.clicked.connect(self.on_plot_all_models) self.clear_models_button.clicked.connect(self.on_clear_models) self.runvpfit_button.clicked.connect(self.on_runvpfit) self.set_resolution.clicked.connect(self.on_resolution) self.help.clicked.connect(self.on_help) self.quit.clicked.connect(self.window.close) # Checkbox `stateChanged` connections: self.cos_fuv_checkbox.stateChanged.connect(self.on_cos_fuv_checkbox) self.cos_nuv_checkbox.stateChanged.connect(self.on_cos_nuv_checkbox) self.include_checkbox.stateChanged.connect(self.on_include_checkbox) # Set up grid layout: grid = QGridLayout() grid.setSpacing(10) # Add widgets: grid.addWidget(self.text_output, 1, 1, 4, 3) grid.addWidget(self.load_button, 1, 4) grid.addWidget(self.save_button, 2, 4) grid.addWidget(self.preview_button, 3, 4) grid.addWidget(self.clear_button, 4, 4) grid.addWidget(self.refresh_plot_button, 1, 5) grid.addWidget(self.plot_model_button, 2, 5) grid.addWidget(self.plot_all_models_button, 3, 5) grid.addWidget(self.clear_models_button, 4, 5) grid.addWidget(self.runvpfit_button, 1, 6) grid.addWidget(self.cos_fuv_checkbox, 2, 6) grid.addWidget(self.cos_nuv_checkbox, 3, 6) grid.addWidget(self.include_checkbox, 4, 6) grid.addWidget(self.set_resolution, 1, 7) grid.addWidget(self.help, 3, 7) grid.addWidget(self.quit, 4, 7) # Place plotting canvas above the options grid: vbox = QVBoxLayout() vbox.addWidget(self.canvas) vbox.addLayout(grid) # Set the layout to the host widget: self.main_frame.setLayout(vbox) # Store all static elements (can be very slow to re-draw these): self.canvas.draw() self.backgrounds = [self.canvas.copy_from_bbox(ax.bbox) for ax in self.axes] # Plot the data: self.plot_data(wavelength, flux, error, continuum, redshift, **self.options['DATA']) # Set the window title: self.window.setWindowTitle('vpguess z = {0:.3f}'.format(self.redshift)) # Give keyboard focus to the figure: self.canvas.setFocusPolicy(Qt.StrongFocus) self.canvas.setFocus() # Variable defaults: self.cos_fuv = False self.cos_nuv = False self.include = False self.last_loaded = None self.resolution = None # Keypress variables: self.previous_keypress = None self.previous_wavelength = None # Set up the key-press events: self.canvas.mpl_connect('key_press_event', self.on_keypress) # Set the main frame as the central widget: self.window.setCentralWidget(self.main_frame) # Resize the window so it will display the canvas with the # requested size: layout_height = vbox.sizeHint().height() layout_width = vbox.sizeHint().width() status_bar_height = self.window.statusBar().sizeHint().height() height = layout_height + status_bar_height self.window.resize(layout_width, height) # Re-do labels: del self.texts[:] self.text(0.45, 0.02, 'Velocity offset (km s$^{-1}$)') self.text(0.01, 0.57, 'Transmission', rotation=90) # Disable any existing callbacks: self.cids = dict() cids1 = list(self.canvas.callbacks.callbacks['key_press_event']) cids2 = list(self.canvas.callbacks.callbacks['button_press_event']) cids = cids1 + cids2 for cid in cids: self.canvas.callbacks.disconnect(cid) # Connect new callbacks: self.connect() def update_plot(self, redshift): # Restore background regions: [self.canvas.restore_region(background) for background in self.backgrounds] # Plot data: [data.pop(0).remove() for data in self.data] self.plot_data( self.wavelength, self.flux, self.error, self.continuum, redshift, **self.options['DATA']) # Draw the artists: for artists in self.data: for element in artists: ax = element.get_axes() ax.draw_artist(element) # Plot the models (if any): if self.options['MODEL']['absorbers'] is not None: self.plot_models(resolution=self.resolution, convolve_with_cos_fuv=self.cos_fuv, convolve_with_cos_nuv=self.cos_nuv, **self.options['MODEL']) # Draw the artists: for artists in self.models: for element in artists: ax = element.get_axes() ax.draw_artist(element) # Draw new panel labels: for i, transition in enumerate(self.transitions): ax = self.axes[self._ind[i]] transf = blended_transform_factory(ax.transAxes, ax.transData) name = transition.name # Use TeX fonts if specified: if self.usetex: name = name.split() if name[0][1].islower(): name = name[0][:2] + '$\;$\\textsc{' + \ name[0][2:].lower() + '} $\lambda$' + name[1] else: name = name[0][:1] + '$\;$\\textsc{' + \ name[0][1:].lower() + '} $\lambda$' + name[1] label = ax.text(0.03, 0.5, name, fontsize=self.label_fontsize, bbox=bbox, transform=transf) ax.draw_artist(label) # Update: self.canvas.update() self.window.setWindowTitle( 'vpguess z = {0:.3f}'.format(self.redshift)) @staticmethod def concatenate_results(): from glob import glob results = glob('*.result') with open('.all_results', 'wb') as combined: for result in results: with open(result, 'rb') as single: combined.write(single.read()) @pyqtSlot(str) def on_output(self, output): self.text_output.moveCursor(QTextCursor.End) self.text_output.insertPlainText(output) def on_load(self): self.text_output.clear() directory = os.getcwd() filename = QFileDialog.getOpenFileName( self.window, 'Select f26 file', directory) with open(filename, 'rb') as f26: self.text_output.setText(f26.read()) self.last_loaded = filename def on_save(self): directory = os.getcwd() filename, ok = QFileDialog.getSaveFileName( self.window, 'Save f26 file', directory) with open(filename, 'w') as f26: f26.write(str(self.text_output.toPlainText())) self.text_output.clear() self.last_loaded = None def on_preview(self): self.concatenate_results() with open('.f26_preview', 'wb') as preview: with open('.all_results', 'rb') as results: preview.write(str(self.text_output.toPlainText())) preview.write(results.read()) f26 = read_f26('.f26_preview') self.options['MODEL']['absorbers'] = f26.absorbers self.update_plot(self.redshift) def on_clear(self): self.text_output.clear() self.last_loaded = None def on_refresh(self): self.update_plot(self.redshift) def on_plot_model(self): directory = os.getcwd() filename = QFileDialog.getOpenFileName( self.window, 'Select f26 file', directory) f26 = read_f26(filename) self.options['MODEL']['absorbers'] = f26.absorbers if f26.absorbers is not None: self.update_plot(self.redshift) def on_plot_all_models(self): self.concatenate_results() f26 = read_f26('.all_results') self.options['MODEL']['absorbers'] = f26.absorbers if f26.absorbers is not None: self.update_plot(self.redshift) def on_clear_models(self): self.options['MODEL']['absorbers'] = None self.update_plot(self.redshift) def on_runvpfit(self): from .vpfit import run_vpfit directory = os.getcwd() if self.last_loaded is not None: filename = self.last_loaded if self.text_output.document().isModified(): with open(filename, 'w') as f26: f26.write(str(self.text_output.toPlainText())) else: filename = QFileDialog.getSaveFileName( self.window, 'Save f26 file', directory) with open(filename, 'w') as f26: f26.write(str(self.text_output.toPlainText())) self.concatenate_results() inc = '.all_results' if self.include else None self.text_output.clear() fwhm = self.resolution if self.resolution is not None else 10 run_vpfit(filename, inc, fwhm=fwhm, cos_fuv=self.cos_fuv, cos_nuv=self.cos_nuv) self.concatenate_results() f26 = read_f26('.all_results') self.options['MODEL']['absorbers'] = f26.absorbers if f26.absorbers is not None: self.update_plot(self.redshift) self.last_loaded = None def on_cos_fuv_checkbox(self, state): if state == Qt.Checked: self.cos_fuv = True else: self.cos_fuv = False def on_cos_nuv_checkbox(self, state): if state == Qt.Checked: self.cos_nuv = True else: self.cos_nuv = False def on_include_checkbox(self, state): if state == Qt.Checked: self.include = True else: self.include = False def on_resolution(self): resolution, ok = SpectralResolutionDialog.get_spectral_resolution( self.main_frame) if ok: self.resolution = resolution def on_help(self): QMessageBox.information(self.main_frame, 'Help', info, False) def on_buttonpress(self, event): if event.inaxes is None: return i = self.axes.index(event.inaxes) transition = self.transitions[np.where(self._ind == i)[0]] z = (1 + event.xdata / c_kms) * (1 + self.redshift) - 1 wavelength = transition.wavelength.value * (1 + z) isort = np.argsort(self.ticks['wavelength']) wavelengths = self.ticks['wavelength'][isort] transitions = self.ticks['transition'][isort] idx = wavelengths.searchsorted(wavelength) wavelength = wavelengths[idx] transition = atom.get_transition(transitions[idx]) z = wavelength / transition.wavelength.value - 1 message = '{0}, z = {1:.3f}'.format(transition.name, z) QMessageBox.information(self.main_frame, 'Transition', message, False) def on_keypress(self, event): if event.key == ' ' and event.inaxes is not None: z = self.redshift # Get amount to add to redshift: dz = (event.xdata / c_kms) * (1 + z) # Get new axis limits, if any: vmin, vmax = event.inaxes.get_xlim() self.vmin = min(0, vmin) self.vmax = max(0, vmax) self.update_plot(z + dz) if event.key == 'z': redshift, ok = QInputDialog.getText( self.main_frame, 'New Redshift', 'Enter redshift: ', False) if ok: self.update_plot(float(redshift)) if event.key == 'b': i = self.axes.index(event.inaxes) transition = self.transitions[np.where(self._ind == i)[0]] z = (1 + event.xdata / c_kms) * (1 + self.redshift) - 1 wavelength = transition.wavelength.value * (1 + z) if (self.previous_keypress == 'b' and self.previous_wavelength is not None): wmin = self.previous_wavelength wmax = wavelength if wmin > wmax: wmin, wmax = wmax, wmin print('%% {0} 1 {1:.3f} {2:.3f} vfwhm=10.0'.format( self.filename, wmin, wmax)) self.previous_keypress = None self.previous_wavelength = None else: self.previous_wavelength = wavelength if event.key == 'l': from ..calculations.absorption import logn_from_tau_peak i = self.axes.index(event.inaxes) transition = self.transitions[np.where(self._ind == i)[0]] z = (1 + event.xdata / c_kms) * (1 + self.redshift) - 1 wavelength = transition.wavelength.value * (1 + z) index = self.wavelength.searchsorted(wavelength) flux = self.flux[index - 1:index + 1] error = self.error[index - 1:index + 1] continuum = self.continuum[index - 1:index + 1] flux_norm = flux / continuum error_norm = error / continuum valid = (error_norm > 0) & ~np.isnan(flux_norm) if not any(valid): print('No good pixels!') return flux_norm = np.median(flux_norm[valid]) error_norm = np.median(error_norm[valid]) if flux_norm < error_norm: flux_norm = error_norm elif flux_norm > 1 - error_norm: flux_norm = 1 - error_norm b = 20 # assume 20 km/s tau = -np.log(flux_norm) logn = logn_from_tau_peak(transition, tau, b) print('{0:6s} {1:8.6f} 0.0 {2:4.1f} 0.0 {3:4.1f} 0.0'.format( transition.parent, z, b, logn)) if event.key == 'S': filename, ok = QInputDialog.getText( self.main_frame, 'Save Figure', 'Enter filename: ', False) if ok: self.savefig(filename) self.previous_keypress = event.key def connect(self): cids = dict() cids['key_press_event'] = self.canvas.mpl_connect( 'key_press_event', self.on_keypress) cids['button_press_event'] = self.canvas.mpl_connect( 'button_press_event', self.on_buttonpress) self.cids.update(cids)
class PythonWidget(QWidget): def __init__(self, parent): super().__init__(parent) self.pythonScript = QTextEdit() self.pythonScript.setReadOnly(False) # asked by Manolo self.pythonScript.setMaximumHeight(340) script_box = oasysgui.widgetBox(self, "", addSpace=False, orientation="vertical", height=545, width=750) script_box.layout().addWidget(self.pythonScript) console_box = oasysgui.widgetBox(script_box, "", addSpace=False, orientation="vertical", height=150, width=750) self.console = PythonConsole(self.__dict__, self) console_box.layout().addWidget(self.console) button_box = oasysgui.widgetBox(script_box, "", addSpace=False, orientation="horizontal") gui.button(button_box, self, "Run Script", callback=self.execute_script, height=35) gui.button(button_box, self, "Save Script to File", callback=self.save_script, height=35) def execute_script(self): self._script = str(self.pythonScript.toPlainText()) self.console.write("\nRunning script:\n") self.console.push("exec(_script)") self.console.new_prompt(sys.ps1) def save_script(self): file_name = QFileDialog.getSaveFileName(self, "Save File to Disk", ".", "*.py") if not file_name is None: if not file_name.strip() == "": file = open(file_name, "w") file.write(str(self.pythonScript.toPlainText())) file.close() QMessageBox.information( self, "QMessageBox.information()", "File " + file_name + " written to disk", QMessageBox.Ok) def setText(self, text): self.pythonScript.clear() self.pythonScript.setText(self.parse_nans(text)) def parse_nans(self, text): return text.replace("nan", "numpy.nan") # -------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------- if __name__ == "__main__": app = QApplication(sys.argv) w = OWmare() w.show() app.exec() w.saveSettings()
class SVNPluginPropsDialog(QDialog): " SVN plugin properties dialog " def __init__(self, plugin, client, path, parent=None): QDialog.__init__(self, parent) self.__plugin = plugin self.__client = client self.__path = path self.__createLayout() self.setWindowTitle("SVN Properties of " + path) self.__populate() self.__propsView.setFocus() return def __populate(self): " Populate the properties list " # Get the currently selected name selectedName = None selected = list(self.__propsView.selectedItems()) if selected: selectedName = str(selected[0].text(0)) self.__propsView.clear() properties = readProperties(self.__client, self.__path) if properties: for itemPath, itemProps in properties: if self.__path == itemPath or \ self.__path == itemPath + os.path.sep: for name, value in itemProps.iteritems(): name = str(name).strip() value = str(value).strip() newItem = QTreeWidgetItem([name, value]) self.__propsView.addTopLevelItem(newItem) self.__resizePropsView() self.__sortPropsView() if selectedName: index = 0 for index in xrange(0, self.__propsView.topLevelItemCount()): item = self.__propsView.topLevelItem(index) if selectedName == item.text(0): item.setSelected(True) return def __resizePropsView(self): " Resizes the properties table " self.__propsView.header().setStretchLastSection(True) self.__propsView.header().resizeSections(QHeaderView.ResizeToContents) return def __sortPropsView(self): " Sorts the properties table " self.__propsView.sortItems( self.__propsView.sortColumn(), self.__propsView.header().sortIndicatorOrder()) return def __createLayout(self): " Creates the dialog layout " self.resize(640, 480) self.setSizeGripEnabled(True) vboxLayout = QVBoxLayout(self) hLayout = QHBoxLayout() self.__propsView = QTreeWidget() self.__propsView.setAlternatingRowColors(True) self.__propsView.setRootIsDecorated(False) self.__propsView.setItemsExpandable(False) self.__propsView.setSortingEnabled(True) self.__propsView.setItemDelegate(NoOutlineHeightDelegate(4)) self.__propsView.itemSelectionChanged.connect( self.__propsSelectionChanged) propsViewHeader = QTreeWidgetItem(["Property Name", "Property Value"]) self.__propsView.setHeaderItem(propsViewHeader) self.__propsView.header().setSortIndicator(0, Qt.DescendingOrder) hLayout.addWidget(self.__propsView) self.__delButton = QToolButton() self.__delButton.setText("Delete") self.__delButton.setFocusPolicy(Qt.NoFocus) self.__delButton.setEnabled(False) self.__delButton.clicked.connect(self.__onDel) hLayout.addWidget(self.__delButton, 0, Qt.AlignBottom) vboxLayout.addLayout(hLayout) # Set property part setGroupbox = QGroupBox(self) setGroupbox.setTitle("Set Property") setLayout = QGridLayout(setGroupbox) setLayout.addWidget(QLabel("Name"), 0, 0, Qt.AlignTop | Qt.AlignRight) setLayout.addWidget(QLabel("Value"), 1, 0, Qt.AlignTop | Qt.AlignRight) self.__nameEdit = QLineEdit() self.__nameEdit.textChanged.connect(self.__nameChanged) setLayout.addWidget(self.__nameEdit, 0, 1) self.__valueEdit = QTextEdit() self.__valueEdit.setAcceptRichText(False) self.__valueEdit.textChanged.connect(self.__valueChanged) metrics = QFontMetrics(self.__valueEdit.font()) rect = metrics.boundingRect("X") self.__valueEdit.setFixedHeight(rect.height() * 4 + 5) setLayout.addWidget(self.__valueEdit, 1, 1) self.__setButton = QToolButton() self.__setButton.setText("Set") self.__setButton.setFocusPolicy(Qt.NoFocus) self.__setButton.setEnabled(False) self.__setButton.clicked.connect(self.__onSet) setLayout.addWidget(self.__setButton, 1, 2, Qt.AlignBottom | Qt.AlignHCenter) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( setGroupbox.sizePolicy().hasHeightForWidth()) setGroupbox.setSizePolicy(sizePolicy) vboxLayout.addWidget(setGroupbox) # Buttons at the bottom buttonBox = QDialogButtonBox(self) buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Ok) buttonBox.button(QDialogButtonBox.Ok).setDefault(True) buttonBox.accepted.connect(self.close) vboxLayout.addWidget(buttonBox) return def __onSet(self): " Triggered when propery set is clicked " name = self.__nameEdit.text().strip() value = self.__valueEdit.toPlainText().strip() try: commitInfo = self.__client.propset(name, value, self.__path) if commitInfo: logging.info(str(commitInfo)) self.__populate() self.__plugin.notifyPathChanged(self.__path) self.__nameEdit.clear() self.__valueEdit.clear() self.__propsView.setFocus() except pysvn.ClientError, exc: message = exc.args[0] logging.error(message) return except Exception, exc: logging.error(str(exc)) return
def clear(self): self.urls = [] QTextEdit.clear(self)
class Calibrador(QWidget): def __init__(self, parent=None): super(Calibrador, self).__init__(parent) layout = QVBoxLayout() self.btabrir = QPushButton('Abrir') self.btabrir.clicked.connect(self.abrirArchivo) layout.addWidget(self.btabrir) self.gb1 = QGroupBox('Valores a Calibrar') l1 = QVBoxLayout() self.lx1 = QLabel('Archivo X1') self.x1 = QLineEdit() self.x1.setReadOnly(True) l1.addWidget(self.lx1) l1.addWidget(self.x1) self.lx2 = QLabel('Archivo X2') self.x2 = QLineEdit() self.x2.setReadOnly(True) l1.addWidget(self.lx2) l1.addWidget(self.x2) self.gb1.setLayout(l1) layout.addWidget(self.gb1) self.gb2 = QGroupBox('Valores de Referencia') l2 = QVBoxLayout() self.ly1 = QLabel('Archivo Y1') self.y1 = QLineEdit() self.y1.setReadOnly(True) l2.addWidget(self.ly1) l2.addWidget(self.y1) self.ly2 = QLabel('Archivo Y2') self.y2 = QLineEdit() self.y2.setReadOnly(True) l2.addWidget(self.ly2) l2.addWidget(self.y2) self.gb2.setLayout(l2) layout.addWidget(self.gb2) self.btlimpiar = QPushButton('Limpiar') self.btlimpiar.clicked.connect(self.limpiar) layout.addWidget(self.btlimpiar) self.contents = QTextEdit() self.contents.setReadOnly(True) layout.addWidget(self.contents) self.btcalibrar = QPushButton('Calibrar') self.btcalibrar.clicked.connect(self.calibrar) layout.addWidget(self.btcalibrar) self.setLayout(layout) self.setWindowTitle('Calibrador Radiométrico') self.setWindowIcon(QIcon('c:/Users/Juanjo/Pictures/CONAE_chico_transp.ico')) def abrirArchivo(self): f = QFileDialog.getOpenFileName(self, 'Abrir archivo a calibrar', expanduser('~'), 'Textos (*.txt)') nom = f.split('/') if self.x1.text() == '': self.xi = f self.x1.setText(nom[len(nom)-1]) elif self.x2.text() == '': self.xj = f self.x2.setText(nom[len(nom)-1]) elif self.y1.text() == '': self.yi = f self.y1.setText(nom[len(nom)-1]) elif self.y2.text() == '': self.yj = f self.y2.setText(nom[len(nom)-1]) else: self.contents.setText('Limpie los campos para cagar nuevos archivos') def limpiar(self): self.x1.clear() self.x2.clear() self.y1.clear() self.y2.clear() self.contents.clear() def calibrar(self): if self.x1.text() == '' or self.x2.text() == '' or self.y1.text() == '' or self.y2.text() == '': self.contents.setText('Cargue todos los archivos antes de calibrar.') else: self.contents.setText('Calibrando...') w, xi, xj, yi, yj = leer(self.xi, self.xj, self.yi, self.yj) if isinstance(xi, list) and isinstance(xj, list) and isinstance(yi, list) and isinstance(yj, list): self.c1, self.c2, pends, ords = corregir(w, xi, xj, yi, yj) crear_archivo(w, self.c1, self.c2, self.x1.text().split('.')[0], self.x2.text().split('.')[0], pends, ords) self.contents.setText('Calibrado.\nArchivos generados en el Escritorio.\n\n' 'Se calibraron los archivos:\n'+self.x1.text()+'\n'+self.x2.text()) else: if isinstance(xi, str): self.contents.setText('Se encontró inconsistencia en los datos contenidos por el archivo: \n\n* ' +self.x1.text()+'\n\n'+'Limpie los campos e ingrese nuevamente archivos ' 'con datos correctos de la forma:\n\nWavelength\tnombre_archivo\n350\t' '7,06635974347591E-03\n351\t7,32030812650919E-03\n...') if isinstance(xj, str): self.contents.setText('* Se encontró inconsistencia en los datos contenidos por el archivo: \n\n* ' +self.x2.text()+'\n\n'+'Limpie los campos e ingrese nuevamente archivos ' 'con datos correctos de la forma:\n\nWavelength\tnombre_archivo\n350\t' '7,06635974347591E-03\n351\t7,32030812650919E-03\n...') if isinstance(yi, str): self.contents.setText('* Se encontró inconsistencia en los datos contenidos por el archivo: \n\n* ' +self.y1.text()+'\n\n'+'Limpie los campos e ingrese nuevamente archivos ' 'con datos correctos de la forma:\n\nWavelength\tnombre_archivo\n350\t' '7,06635974347591E-03\n351\t7,32030812650919E-03\n...') if isinstance(yj, str): self.contents.setText('* Se encontró inconsistencia en los datos contenidos por el archivo: \n\n* ' +self.y2.text()+'\n\n'+'Limpie los campos e ingrese nuevamente archivos ' 'con datos correctos de la forma:\n\nWavelength\tnombre_archivo\n350\t' '7,06635974347591E-03\n351\t7,32030812650919E-03\n...')
class Chat(QFrame): # ======================================================================= def __init__(self, parent=None, _PARENT=None): # ------------------------------------------------------------------- QFrame.__init__(self, parent); # ------------------------------------------------------------------- self.PARENT = _PARENT; self.CONF = _PARENT.CONF; self.setGeometry(3, 5, 975, 548); self.setStyleSheet( "QFrame{ font: 12px 'monospace'; color: #000; background-color: transparent; background-image: url('./data/imgs/TAB_Chat.png'); }" ); # ------------------------------------------------------------------- self.CHAT_URL = "https://btc-e.com/"; self.CHAT_DATA = []; self.CHAT_LANG = self.CONF["USER"]["CHAT_LANG"]; self.CHAT_HEADERS = { "User-Agent" : "Mozilla/5.0 (Win-32; rv:24.0) Gecko/20140723 Firefox/24.0 Iceweasel/24.7.0", "Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language" : "en-US,en;q=0.5", "Referer" : "https://btc-e.com/", "Connection" : "keep-alive", "Cache-Control" : "max-age=0", "Cookie" : "" } self.CHAT_TIMER = QTimer(); #self.CHAT_BG_COLOR = "#555"; self.CHAT_BG_COLOR = "#0F0"; self.CHAT_ALLOW_UPD = False; # ------------------------------------------------------------------- self.CHAT_WIDGET = QTextEdit( self ); self.CHAT_WIDGET.setGeometry( 13, 116, 690, 388 ); self.CHAT_WIDGET.setStyleSheet( "QTextEdit{ background-color: transparent; color: #fff; background-image: url(''); }" ); self.CHAT_WIDGET.setReadOnly( True ); self.LANG_COMBO = QComboBox( self); self.LANG_COMBO.setGeometry( 86, 20, 108, 44 ); self.connect( self.LANG_COMBO, SIGNAL('currentIndexChanged(int)'), self.CHANGE_CHAT_LANG ); self.LANG_COMBO.setEditable(False); self.NEW_MSG = QLineEdit("", self); self.NEW_MSG.setGeometry( 20, 510, 500, 30 ); self.NEW_MSG.setStyleSheet(" QLineEdit{ border-style: none; background-color: #333; color: #fff; background-image: url(''); }"); self.NEW_MSG.setPlaceholderText(" Enter message:"); self.SEND = QPushButton(" Send", self); self.SEND.setGeometry( 593, 510, 90, 30 ); #self.SEND.setStyleSheet( "QPushButton{ background-color: transparent; border-style: none; }" ); #self.connect( self.SEND, SIGNAL('clicked()'), lambda: self.SEND_VALUES_TO_TRADE_TERMINAL("SEND_VALUES") ); # ------------------------------------------------------------------- self.ALLOW_UPDATE_CHECKBOX = QCheckBox("", self); self.ALLOW_UPDATE_CHECKBOX.setGeometry( 335, 83, 17, 17 ); self.ALLOW_UPDATE_CHECKBOX.setCheckState(Qt.Unchecked); self.connect(self.ALLOW_UPDATE_CHECKBOX, SIGNAL('stateChanged(int)'), self.CHANGE_VALUES ); self.UPDATE_NOW_BTN = QPushButton("Update Now!", self); self.UPDATE_NOW_BTN.setGeometry( 360, 74, 94, 24 ); self.connect( self.UPDATE_NOW_BTN, SIGNAL('clicked()'), self.UPDATE_NOW ); # ------------------------------------------------------------------- self.INIT(); # ------------------------------------------------------------------- # ======================================================================= def INIT(self): # ------------------------------------------------------------------- try: self.INIT_CHAT_COMBO(); self.UPDATE(); except Exception as _exception: print("-----------------------------------------------------"); print("[INIT]"+str(_exception)); # ------------------------------------------------------------------- # ======================================================================= def UPDATE_NOW(self): # ------------------------------------------------------------------- self.CHAT_ALLOW_UPD = True; self.UPDATE(); self.CHAT_ALLOW_UPD = False; # ------------------------------------------------------------------- # ======================================================================= def UPDATE(self): # ------------------------------------------------------------------- #print("UPDATE:") # ------------------------------------------------------------------- try: if self.CHAT_ALLOW_UPD: self.GET_DATA(); self.CHAT_WIDGET.clear(); for msg in self.CHAT_DATA: # --------------------------------------------------------------- """ print(msg["time"]); print(msg["nick"]); print(msg["msg"]); """ # --------------------------------------------------------------- item = '<p style="background-color: #555;">'; item += "[<span style='color: #000;'>"+msg["time"].split(" ")[1]+"</span>] : "; if msg["nick"] == "admin": item += "[<span style='color: #f00; font-weight: bold;'>"+msg["nick"]+"</span>]<br/><br/>"; else: item += "[<span style='color: #000; font-weight: bold;'>"+msg["nick"]+"</span>]<br/><br/>"; item += msg["msg"]+"<br/>"; item += "</p>"; self.CHAT_WIDGET.append(item); # --------------------------------------------------------------- self.CHAT_TIMER.singleShot( self.CONF["SYS"]["UPD_DELAY"], self.UPDATE ); except Exception as e: print("CHAT[0:0]"+str(e)) self.CHAT_TIMER.singleShot( self.CONF["SYS"]["UPD_DELAY"], self.UPDATE ); # ------------------------------------------------------------------- # ======================================================================= def CHANGE_VALUES(self): # ------------------------------------------------------------------- if self.ALLOW_UPDATE_CHECKBOX.isChecked(): self.CHAT_ALLOW_UPD = True; else: self.CHAT_ALLOW_UPD = False; # ------------------------------------------------------------------- # ======================================================================= def GET_DATA(self): # ------------------------------------------------------------------- try: self.CHAT_HEADERS["Cookie"] = "chatRefresh=1; locale="+self.CHAT_LANG+";" req = urllib2.Request(self.CHAT_URL, headers=self.CHAT_HEADERS); resp = urllib2.urlopen(req).read(); CHAT = BeautifulSoup( resp ).body.find('div', attrs={'id':'nChat'}); self.CHAT_DATA = []; for data in CHAT: self.CHAT_DATA.append( { "msg_id": data["id"], "nick":data.a.string, "time": data.a["title"], "msg": data.span.string } ); except Exception as e: print("CHAT[0:1]"+str(e)) # ------------------------------------------------------------------- # ======================================================================= def CHANGE_CHAT_LANG(self): # ------------------------------------------------------------------- self.CHAT_LANG = str(self.LANG_COMBO.currentText()).lower().strip(); #print(self.CHAT_LANG); # ------------------------------------------------------------------- # ======================================================================= def INIT_CHAT_COMBO(self): # ------------------------------------------------------------------- for LANG in self.CONF["USER"]["CHAT_LANGS"]: self.LANG_COMBO.addItem(LANG.upper()); for i in xrange(0, self.LANG_COMBO.__len__()): self.LANG_COMBO.setItemData( i, QColor("#333"),Qt.BackgroundRole ); self.LANG_COMBO.setItemData( i, QColor("#fff"),Qt.ForegroundRole );
class MainWindow(QMainWindow): """ MainWindow(QMainWindow) This is the class/object for the main window of the GUI application. This main window and GUI applicaiton are a Single Document Interface (SDI) Application. """ # --------------------------------------------------------------------------- def __init__(self, parent = None): """ MainWindow constructor """ # Text messages for the class are set here self.genericMsg = "WARNING -- Your changes have NOT been saved.\nAre you sure you want to %s\nand lose all of your changes?" self.quit_msg = self.genericMsg %"exit the program" self.new_msg = self.genericMsg %"start a new file" self.open_msg = self.genericMsg %"open a new file" self.close_msg = self.genericMsg %"close this file" self.testcases = [] # \ self.testsuitefolder = "" # \__ Start with a clean slate. # Read the confuration file data into the local class namespace as the # class will need this information. try: self.configs = {} self.configs = configFile2dictionary(CONFIG_FILE) # print self.configs if len(self.configs) == 0: raise Exception ("Failed to read configurations from \"%s\"" %CONFIG_FILE) self.configs['testcasefolder'] = os.path.join(MY_PATH, self.configs['testcasefolder']) self.configs['resultshome'] = os.path.join(MY_PATH, self.configs['resultshome']) except Exception as e: # TODO: SHow this as a message box as well print e print "Using default configurations" self.configs['testcasefolder'] = "/tmp/testcases" self.configs['resultshome'] = "/var/www/html/results" # Call to the Super Class for QT MainWindow super(MainWindow, self).__init__() # Don't ask, just do it. # Set up a way to write to the Console Area in from a separate thread. This # allows for real-time output to the consoleArea. self.consoleMessage = pyqtSignal(str) self.connect(self, SIGNAL("self.consoleMessage"), self.updateConsole) # Set up a way to write to the Debug Area from a separate thread. This # allows for real-time output to the consoleArea. self.debugMessage = pyqtSignal(str) self.connect(self, SIGNAL("self.debugMessage"), self.updateDebug) # Set up a way to write to the Results Area from a separate thread. This # allows for real-time output to the resultsArea. self.resultsMessage = pyqtSignal(str) self.connect(self, SIGNAL("self.resultsMessage"), self.updateResults) # The Steps for creating the main windows self.create_menubarActions() self.create_menubar() self.create_toolbarActions() self.create_toolbar() self.createWidgets() self.paint_mainWindow() self.setState(0) # This needs fixed, see setState() # --------------------------------------------------------------------------- def create_menubarActions(self): # # Create the menubar actions that will server as the link between # menubar items and function calls. NOTE: Every 'triggered' argument # must point to a valid function. # File Menu Actions - - - - - - - - - - - - - - - - - - - - - - - - - - - self.mbExit = QAction( "E&xit", self, shortcut="Alt+E", statusTip="Exit the application", triggered=self.cleanExit) self.mbNew = QAction( "N&ew", self, shortcut="Alt+N", statusTip="Create a new file", triggered=self.newFile) self.mbOpen = QAction( "O&pen", self, shortcut="Alt+O", statusTip="Open an existing file", triggered=self.openFile) self.mbClose = QAction( "C&lose", self, shortcut="Alt+C", statusTip="Close a file", triggered=self.closeFile) self.mbSave = QAction( "S&ave", self, shortcut="Alt+S", statusTip="Save the file", triggered=self.saveFile) self.mbSaveAs = QAction( "Save A&s", self, shortcut="Alt+A", statusTip="Save a file as", triggered=self.saveAsFile) # Script Menu Actions - - - - - - - - - - - - - - - - - - - - - - - - - - self.mbRun = QAction( "R&un", self, shortcut="Alt+R", statusTip="Run the loaded file", triggered=self.runScript) self.mbStop = QAction( "S&top", self, shortcut="Alt+S", statusTip="Stop script execution ", triggered=self.stopScript) self.mbDebug = QAction( "D&ebug",self, shortcut="Alt+D", statusTip="Debug the loaded file", triggered=self.debugScript) # Help Menu Actions - - - - - - - - - - - - - - - - - - self.mbHelp = QAction( "H&elp", self, shortcut="Alt+H", statusTip="Display help", triggered=self.showHelp) self.mbAbout = QAction( "A&bout", self, shortcut="Alt+A", statusTip="About This program", triggered=self.showAbout) # --------------------------------------------------------------------------- def create_toolbarActions(self): # Create the actions for the toolbar. Status tips and shortcut keys for # the toolbar components are defined here. NOTE: Every 'triggered' # connection must point to a valid function. self.tbExit = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Exit.png')), 'Exit', self) self.tbExit.setShortcut('Ctrl+Q') self.tbExit.setStatusTip('Exit application') self.tbExit.triggered.connect(self.cleanExit) self.tbNew = QAction(QIcon(os.path.join(RESOURCE_PATH, 'New.png')), 'New', self) self.tbNew.setShortcut('Ctrl+N') self.tbNew.setStatusTip('Start a new file') self.tbNew.triggered.connect(self.newFile) self.tbOpen = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Open.png')), 'Open', self) self.tbOpen.setShortcut('Ctrl+O') self.tbOpen.setStatusTip('Open an existing file') self.tbOpen.triggered.connect(self.openFile) self.tbSave = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Save.png')), 'Save', self) self.tbSave.setShortcut('Ctrl+S') self.tbSave.setStatusTip('Save to a file ') self.tbSave.triggered.connect(self.saveFile) self.tbRun = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Run.png')), 'Run', self) self.tbRun.setShortcut('Ctrl+R') self.tbRun.setStatusTip('Run the loaded script') self.tbRun.triggered.connect(self.runScript) self.tbStop = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Stop.png')), 'Stop', self) self.tbStop.setShortcut('Ctrl+S') self.tbStop.setStatusTip('Stop script execution') self.tbStop.triggered.connect(self.stopScript) self.tbDebug = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Debug.png')), 'Debug', self) self.tbDebug.setShortcut('Ctrl+D') self.tbDebug.setStatusTip('Debug script') self.tbDebug.triggered.connect(self.debugScript) self.tbInfo = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Info.png')), 'Info', self) self.tbInfo.setShortcut('Ctrl+O') self.tbInfo.setStatusTip('Info About this program') self.tbInfo.triggered.connect(self.showAbout) self.tbHelp = QAction(QIcon(os.path.join(RESOURCE_PATH, 'Help.png')), 'Help', self) self.tbHelp.setShortcut('Ctrl+H') self.tbHelp.setStatusTip('Help using this program') self.tbHelp.triggered.connect(self.showHelp) # --------------------------------------------------------------------------- def create_toolbar(self): self.toolbar = self.addToolBar('Main') self.toolbar.addAction(self.tbOpen) self.toolbar.addAction(self.tbNew) self.toolbar.addAction(self.tbSave) self.toolbar.addAction(self.tbExit) self.toolbar.addSeparator() # ------------- self.toolbar.addAction(self.tbRun) self.toolbar.addAction(self.tbStop) self.toolbar.addAction(self.tbDebug) self.toolbar.addSeparator() # -------------- self.toolbar.addAction(self.tbHelp) self.toolbar.setIconSize(QSize(50,50)) # --------------------------------------------------------------------------- def create_menubar(self): # Create File Menu self.fileMenu = QMenu("&File") self.fileMenu.addAction(self.mbNew) self.fileMenu.addAction(self.mbOpen) self.fileMenu.addSeparator() self.fileMenu.addAction(self.mbSave) self.fileMenu.addAction(self.mbSaveAs) self.fileMenu.addSeparator() self.fileMenu.addAction(self.mbClose) self.fileMenu.addAction(self.mbExit) # Create Script Menu self.scriptMenu = QMenu("&Script") self.scriptMenu.addAction(self.mbRun) self.scriptMenu.addAction(self.mbStop) self.scriptMenu.addAction(self.mbDebug) # Create Help Menu self.helpMenu = QMenu("&Help") self.helpMenu.addAction(self.mbHelp) self.helpMenu.addAction(self.mbAbout) # Add menus to menubar menubar = self.menuBar() menubar.addMenu(self.fileMenu) menubar.addMenu(self.scriptMenu) menubar.addMenu(self.helpMenu) # --------------------------------------------------------------------------- def createWidgets(self): # Create the widgets used in the main window and other parts of the script. # --- Text Area ---- self.textArea = QTextEdit() # Text editor self.textArea.setFont(QFont("Courier", 14)) # Keepin' it simple # -- Console Area --- self.consoleArea = QTextEdit() # Console Area consolePalette = QPalette() # A bit more complex bgColor = QColor(0, 0, 0) # Green Text with txColor = QColor(0, 255, 0) # Black background consolePalette.setColor(QPalette.Base, bgColor) # consolePalette.setColor(QPalette.Text, txColor) # self.consoleArea.setPalette(consolePalette) # self.consoleArea.setFont(QFont("Courier", 14)) # Font name and size self.consoleArea.setReadOnly(True) # Read only # --- Debug Area --- self.debugArea = QTextEdit() # Debug Area debugPalette = QPalette() # Palette for area bgColor = QColor(0, 0, 0) # Black Background debugPalette.setColor(QPalette.Base, bgColor) # txColor = QColor(255, 0, 0) # Red Text debugPalette.setColor(QPalette.Text, txColor) # self.debugArea.setPalette(debugPalette) # self.debugArea.setFont(QFont("Courier", 14)) # Font name and size self.debugArea.setReadOnly(True) # Read only # --- Results Area --- self.resultsArea = QTextEdit() # Results Area consolePalette = QPalette() # A bit more complex bgColor = QColor(0, 0, 0) # White Text with txColor = QColor(255, 255, 255) # Black background consolePalette.setColor(QPalette.Base, bgColor) # consolePalette.setColor(QPalette.Text, txColor) # self.resultsArea.setPalette(consolePalette) # self.resultsArea.setFont(QFont("Courier", 10)) # Font name and size self.resultsArea.setReadOnly(True) # Read only # --- Tab Area --- self.tabs = QTabWidget() # Tabs self.tabs.addTab(self.consoleArea, 'Console') # Add Console Area tab self.tabs.addTab(self.debugArea, 'Debug' ) # Add Debug Area tab self.tabs.addTab(self.resultsArea, 'Results') # Add Results Area tab # TODO: Change the tab indexes to meaningful words not just 0,1,2 self.tabs.setTabIcon(0, QIcon(os.path.join(RESOURCE_PATH, "Run.png" ))) # Add Icon to tab self.tabs.setTabIcon(1, QIcon(os.path.join(RESOURCE_PATH, "Debug.png" ))) # Add Icon to tab self.tabs.setTabIcon(2, QIcon(os.path.join(RESOURCE_PATH, "results.png" ))) # Add Icon to tab self.tabs.setIconSize(QSize(30,30)) self.tabs.setTabShape(QTabWidget.Triangular) # Set tab shape # --------------------------------------------------------------------------- def paint_mainWindow(self): # Define and use a "Grid Layout" for the main window. grid = QGridLayout() grid.addWidget(self.textArea, 1, 1) grid.addWidget(self.tabs, 2, 1) # Create central widget, add layout, and set central_widget = QWidget() central_widget.setLayout(grid) self.setCentralWidget(central_widget) # Fun feature for users. If you are going to have a toolbar then you # really need this status bar to show what the icons do. self.statusbar = QStatusBar(self) self.statusbar.setObjectName( "statusbar") MainWindow.setStatusBar(self, self.statusbar) self.statusbar.show() # Initial settings for the main window # # Set the Main Window Geometry top = 100 # Main Window initial 'top' position (as pixels from top of screen) left = 100 # Main Window initial 'left' position (as pixels from left side of screen) width = 1000 # Main Window initial 'width' (as pixels) height = 700 # Main Window initial 'height' (as pixels) self.setGeometry(QRect(top, left, width, height)) # Create connection(s) # If the contents of the text area are changed then call a function # to set the appropriate file menu state. This file menu state can # also be used to ensure clean exits. In english, keep track # of changes to the text editor. It affects the "state" of the # application. See setState() self.connect(self.textArea, SIGNAL("textChanged()"), self.textChanged) # --------------------------------------------------------------------------- def cleanExit(self): # Provides an "ARE YOU SURE" method for clean exits. if self.state == 2: # See setState() reply = QMessageBox.question(self, 'Message', self.quit_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: qApp.quit() else: pass else: qApp.quit() # --------------------------------------------------------------------------- def newFile(self): # Start a new file. However, if a file is already open AND has not been # saved, then we prompt the user before starting a new file. # Remember, we are implementing SDI behavior, google it. if self.state == 2: reply = QMessageBox.question(self, 'Message', self.new_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.inputFile = '' self.setState(1) self.updateDebug("New File Started") else: self.updateDebug("New File Aborted") else: self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.inputFile = '' self.setState(1) self.updateDebug("New File Started") #---------------------------------------------------------------------------- def openFile(self): # Open a new file. However, if a file is already open AND has not been # saved, then we prompt the user before opening a new file. # Remember, we are implementing SDI behavior, google it. if self.state == 2: reply = QMessageBox.question(self, 'Message', self.open_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.inputFile = '' self.setState(1) # Let's go ahead and load the file. self.loadScript() else: self.updateDebug("Open File aborted") else: self.inputFile = QFileDialog.getOpenFileName(self, 'Open File', '.') fname = open(self.inputFile) data = fname.read() self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.textArea.setText(data) fname.close() self.setState(1) # Let's go ahead and load the file. self.loadScript() # --------------------------------------------------------------------------- def closeFile(self): # Close the open file and return to the initial/unopened state. # A clean exit has been implemented if self.state == 2: reply = QMessageBox.question(self, 'Message', self.close_msg, QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.inputFile = "" self.setState(0) else: self.updateDebug("Close File aborted") else: self.textArea.clear() self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.inputFile = "" self.setState(0) # --------------------------------------------------------------------------- def saveFile(self): # save the contents of text editor to a file if self.inputFile == "": self.saveAsFile() else: if len(self.inputFile) > 0: filePointer = open(self.inputFile, 'w') filePointer.write(self.textArea.toPlainText()) filePointer.close() self.setState(1) # Set initial menu state self.loadScript() else: # TODO: Add message box warning here pass # --------------------------------------------------------------------------- def saveAsFile(self): # save the contents of text editor to a file filename = "" filename = QFileDialog.getSaveFileName(self, 'Save File', self.inputFile) if len(filename) > 0: filePointer = open(filename, 'w') filePointer.write(self.textArea.toPlainText()) filePointer.close() self.inputFile = filename # Set to the new file name self.setState(1) # Set initial menu state self.loadScript() else: # TODO: Add message box warning here pass # --------------------------------------------------------------------------- def checkScript(self): """ Checks to see if the loaded script "test suite" is valid. Returns the number of errors found in the script "test suite". A valid script "test suite" has noting but: - Comment lines, starting with '#' - Blank lines, contain nothing but white space - Filename lines, lines with the name of testcase filenames Anything else is considered an error. We also take the liberty of verfying that all files (testcases) listed actually exist. Non-existant testcases are also errors. The details of this check are listed in the debug tab of the main window. """ errorCount = 0 self.testcases = [] self.updateDebug("Checking... ") lines = self.textArea.toPlainText().split('\n') lineNumber = 0 for line in lines: lineNumber += 1 line = str(line) line = line.strip() if len(line) > 0: if line[FIRST] != '#': if os.path.exists(line): self.updateDebug("Console line %d: OK." %lineNumber) self.testcases.append(line) else: self.updateDebug("Console line %d: Unable to find test case \"%s\"." %(lineNumber, line)) errorCount += 1 else: self.updateDebug("Console line %d: Skipped as comment." %lineNumber) else: self.updateDebug("Console line %d: Skipped as whitespace." %lineNumber) lineNumber = lineNumber +1 self.updateDebug("Checked, found %d Error(s)" %errorCount ) return errorCount # --------------------------------------------------------------------------- def loadScript(self): self.updateDebug("Loading \"%s\"" %self.inputFile) errors = self.checkScript() if errors == 0: self.consoleArea.clear() self.debugArea.clear() self.resultsArea.clear() self.setState(4) self.updateDebug("Loaded \"%s\"" %self.inputFile) self.updateConsole("Loaded \"%s\"" %self.inputFile) else: msg = "This script has errors and cannot be executed.\n" msg += "\nSee the Debug Tab for details." QMessageBox.critical(self, "Script Error", msg, QMessageBox.Ok) self.setState(3) self.updateConsole("Failed to load \"%s\"\nSee Debug tab for details." %self.inputFile) # --------------------------------------------------------------------------- def threadedExecution(self, threadBuffer): """ This is the threaded execution of the test cases. While in this thread/function please only use "self.emit(SIGNAL, message)" for outputs to the tabs (console, debug, and results). Any other attempt to update the tabs will raise an unhandled tread exception. """ try: self.setState(5) # Runing test # Entered Threaded Execution message = "Executing %d testcases" %len(self.testcases) self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) # For Results Report reportTime = time.strftime("%A, %B %d, %Y (%H:%M:%S)", time.localtime()) message = """ Test Report for test suite: %s %s Test Cases in Suite:\n""" %(self.inputFile ,reportTime) counter = 0 # for t in self.testcases: # Add a neatly counter = counter + 1 # printed list message = message + " %2d %s\n" %(counter, t) # of test cases message = message + """ Results Detailed in: %s Results Summary: """ %self.testsuitefolder self.emit(SIGNAL("self.resultsMessage"), message) # Loop through each of the test cases and create subfolders for each # testcase as we go testcaseCounter = 0 numberOfTestcases = len(self.testcases) for testcase in self.testcases: # Loop/testcase Counter testcaseCounter += 1 # Initial Testcase Message message = "Starting testcase %d of %d %s" %(testcaseCounter, numberOfTestcases, testcase) self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) # Create the folder for the testcase testcasename = os.path.split(testcase)[LAST].split('.')[FIRST] testcasefolder = os.path.join(self.testsuitefolder, testcasename) message = "Creating testcase folder: %s" % testcasefolder self.emit(SIGNAL("self.debugMessage" ), message) # TODO: Put this make folder in a try/except block os.mkdir(testcasefolder) message = "Created testcase folder: %s" % testcasefolder self.emit(SIGNAL("self.debugMessage" ), message) # Execute the test case. message = "Executing: %s" % testcase self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) # *** ******************* *** # *** TEST CASE EXECUTION *** # *** ******************* *** c = am_Command.Command("%s %s " %(testcase, testcasefolder)) c.run() testcaseResults = c.returnResults() message = " Command:\n%s\n Output:\n%s\n Errors: \n%s\n Return: %s\n" %(testcaseResults["command"] , testcaseResults["output"] , testcaseResults["error"] , testcaseResults["returnCode"]) self.emit(SIGNAL("self.debugMessage" ), message) if testcaseResults['returnCode'] == 0: message = "Testcase %s PASSED" %testcasename else: message = "Testcase %s FAILED" %testcasename self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) self.emit(SIGNAL("self.resultsMessage"), message) # Write the output and error files to the testcase folder # TODO: Put these file writes in try/except blocks if len(testcaseResults['output']) > 0: message = "Writing output file to testcase folder %s" %testcasefolder self.emit(SIGNAL("self.debugMessage" ), message) f = open(os.path.join(testcasefolder,"output.txt"), 'w') f.write(testcaseResults['output']) f.close() if len(testcaseResults['error']) > 0: message = "Writing error file to testcase folder %s" %testcasefolder self.emit(SIGNAL("self.debugMessage" ), message) f = open(os.path.join(testcasefolder, "errors.txt"), 'w') f.write(testcaseResults['error']) f.close() # Final Message for this testcase message = "Completed testcase %d of %d" %(testcaseCounter, numberOfTestcases) self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) # We are now out of the loop and done with all testcase executions. message = "Testcase execution complete, see Results tab for details." self.emit(SIGNAL("self.consoleMessage"), message) self.emit(SIGNAL("self.debugMessage" ), message) # Report Footer message = "--- END OF REPORT ---" self.emit(SIGNAL("self.resultsMessage"), message) # Show the Results tab when the test suite is fnished. time.sleep(3) # Wait for the buffer. It may take a few self.tabs.setCurrentIndex(2) # secons to write the last message to the # # tab's text area. # Write the report to the "report.txt" file in the test suite results # folder # TODO: Put this file write in a try/except block. summaryReportFilename = os.path.join(self.testsuitefolder, "SummaryRepot.txt") f = open(summaryReportFilename, 'w') f.write(self.resultsArea.toPlainText()) f.close() self.setState(7) # Finished test case executions except Exception as e: print e # --------------------------------------------------------------------------- def runScript(self): """ Wrapper for the threaded execution. """ # Make sure we have a results home foldder message = "Checking results home folder" self.updateDebug(message) if not os.path.exists(self.configs['resultshome']): message = "Creating Results home: %s" %self.configs['resultshome'] self.updateDebug(message) try: os.mkdir(resultsHome) message = "Created Results home: %s" %self.configs['resultshome'] self.updateDebug(message) except: message = "Unable to create the Results Home folder.\n%s" % self.configs['resultshome'] self.updateDebug(message) QMessageBox.critical(self, "Script Error", message, QMessageBox.Ok) self.setState(3) return else: message = "Results home using: %s" %self.configs['resultshome'] self.updateDebug(message) # Create the test suite folder using a timestamp. timestamp = time.strftime("%Y%m%d-%H%M%S", time.localtime()) if os.path.exists(self.configs['resultshome']): try: self.testsuitefolder = os.path.join( self.configs['resultshome'], timestamp) message = "Creating Test Suite Folder: %s" %self.testsuitefolder self.updateDebug(message) os.mkdir(self.testsuitefolder) message = "Created Test Suite Folder: %s" %self.testsuitefolder self.updateDebug(message) except: message = "Unable to create the Test Suite folder.\n%s" % self.testsuitefolder self.updateDebug(message) QMessageBox.critical(self, "Script Error", message, QMessageBox.Ok) self.setState(3) return # Spawn the execution thread. Execution is threaded so that the console # and debug tabs can be updated in real time. start_new_thread(self.threadedExecution, (self,)) # -------------------------------------------------------------------------- def stopScript(): pass # TODO: Write this function # -------------------------------------------------------------------------- def debugScript(): pass # TODO: Write this function # -------------------------------------------------------------------------- def showHelp(self): Popen(["/usr/bin/gedit", "readme.txt"], shell=True) # -------------------------------------------------------------------------- def textChanged(self): # Set the file menu state to indicate unsaved changes to text. self.setState(2) # --------------------------------------------------------------------------- def updateConsole(self, message): # Updates the console area consoleText = self.consoleArea.toPlainText() # consoleText += "\n" consoleText += "%s\n" %str(message) self.consoleArea.setText(consoleText) self.consoleArea.moveCursor(QTextCursor.End) # --------------------------------------------------------------------------- def updateDebug(self, message): # Updates the debug area debugText = self.debugArea.toPlainText() # consoleText += "\n" debugText += "%s\n" %str(message) self.debugArea.setText(debugText) self.debugArea.moveCursor(QTextCursor.End) # --------------------------------------------------------------------------- def updateResults(self, message): # Updates the results area consoleText = self.resultsArea.toPlainText() # consoleText += "\n" consoleText += "%s\n" %str(message) self.resultsArea.setText(consoleText) self.resultsArea.moveCursor(QTextCursor.End) # --------------------------------------------------------------------------- def showAbout(self): # Shows the about box aboutTitle = "About %s" %ME aboutText = "Test Case Runner\n%s, Version %s\nNETSCOUT, April 2016\n\nFor support contact:\[email protected]"%(ME, VERSION) QMessageBox.about(self, aboutTitle, aboutText) # -------------------------------------------------------------------------- def textChanged(self): # Set the file menu state to indicate unsaved changes to text. self.setState(2) # --------------------------------------------------------------------------- def setState(self, state): # ------------------------------------------------------------------------ # ************************* STATE MACHINE MANAGEMENT ********************* # ------------------------------------------------------------------------ # The state of the program determines what menubar items or toolbar # buttons are active or even visible. Additionally, some method behavior # may also vary depending on the state of the program. The states are # listed below: # # State 0 : The program is started but no file or editor session is # opened. # State 1 : A file or text editor session is opened but the text is # unchanged since last save. # State 2 : A file or text editor session is opened and the text has # changed since the last save. # State 3 : The text in the editor has errors and cannot be executed. # State 4 : The text in the editor has no errors. # State 5 : The text in the editor is being executed. # State 6 : The text in the editor has been stopped before execution has # completed. # State 7 : The text in the editor has successfully completed. # State 8 : The text in the editor has terminated with errors. self.state = state if self.state == 0: self.mbExit.setEnabled(True) self.mbNew.setEnabled(True) self.mbOpen.setEnabled(True) self.mbClose.setEnabled(False) self.mbSave.setEnabled(False) self.mbSaveAs.setEnabled(False) self.mbRun.setEnabled(False) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(False) self.tbOpen.setEnabled(True) self.tbNew.setEnabled(True) self.tbSave.setEnabled(False) self.tbExit.setEnabled(True) self.tbRun.setEnabled(False) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(False) self.textArea.setVisible(False) self.tabs.setVisible(False) elif self.state == 1: self.mbExit.setEnabled(True) self.mbNew.setEnabled(True) self.mbOpen.setEnabled(True) self.mbClose.setEnabled(True) self.mbSave.setEnabled(False) self.mbSaveAs.setEnabled(False) self.mbRun.setEnabled(True) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbOpen.setEnabled(True) self.tbNew.setEnabled(True) self.tbSave.setEnabled(False) self.tbExit.setEnabled(True) self.tbRun.setEnabled(True) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) self.textArea.setVisible(True) self.tabs.setVisible(True) # self.consoleArea.setVisible(True) # self.debugArea.setVisible(True) elif self.state == 2: self.mbExit.setEnabled(True) self.mbNew.setEnabled(True) self.mbOpen.setEnabled(True) self.mbClose.setEnabled(True) self.mbSave.setEnabled(True) self.mbSaveAs.setEnabled(True) self.mbRun.setEnabled(True) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbOpen.setEnabled(True) self.tbNew.setEnabled(True) self.tbSave.setEnabled(True) self.tbExit.setEnabled(True) self.tbRun.setEnabled(True) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) self.textArea.setVisible(True) self.tabs.setVisible(True) elif self.state == 3: self.mbRun.setEnabled(False) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbRun.setEnabled(False) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) elif self.state == 4: pass elif self.state == 5: self.mbRun.setEnabled(False) self.mbStop.setEnabled(True) self.mbDebug.setEnabled(False) self.tbRun.setEnabled(False) self.tbStop.setEnabled(True) self.tbDebug.setEnabled(False) elif self.state == 6: self.mbRun.setEnabled(True) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbRun.setEnabled(True) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) elif self.state == 7: self.mbRun.setEnabled(True) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbRun.setEnabled(True) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) elif self.state == 8: self.mbRun.setEnabled(True) self.mbStop.setEnabled(False) self.mbDebug.setEnabled(True) self.tbRun.setEnabled(True) self.tbStop.setEnabled(False) self.tbDebug.setEnabled(True) else: pass return
class NoteBook( QFrame ): # ======================================================================= def __init__(self, parent=None): # ------------------------------------------------------------------- QFrame.__init__(self, parent); # ------------------------------------------------------------------- self.PARENT = parent; self.DEBUG = False; self.LOG_TAG = str(self.__class__.__name__).upper(); self.setGeometry( 4, 34, 1012, 606 ); self.setStyleSheet( "QFrame{ font: 12px 'monospace'; color: #fff; background-color: rbga(0,0,0, 190); border-style: solid; border-width: 5px; border-color: #FFF; }" ); # ------------------------------------------------------------------- self.NOTEBOOK_FILE = self.PARENT.STORAGE_ROOT+"notebook.file"; # ------------------------------------------------------------------- self.TEXT = QTextEdit( "TEST: TEST", self ); self.TEXT.setGeometry(5, 35, 980, 560); self.TEXT.setStyleSheet("QTextEdit{ font: 12px 'monospace'; color: #fff; margin: 5px; padding: 5px; border-style: solid; border-width: 1px; border-color: #FFF; }") self.TEXT.setReadOnly( False ); self.TEXT.setAcceptRichText( False ); self.TEXT.setUndoRedoEnabled( True ); self.TEXT.LineWrapMode( self.TEXT.WidgetWidth ); self.TEXT.textChanged.connect( self.TEXT_CHANGED ); # ------------------------------------------------------------------- self.hide(); self.IS_OPEN = False; self.KEEP_OPEN = False; # ------------------------------------------------------------------- self.UPDATE_TIMER = QTimer(); self.UPDATE_TIMER.singleShot( 1000, self.UPDATE_FRAME ); # ------------------------------------------------------------------- self.PARENT.SPLASH.STATUS( self.LOG_TAG+": [INIT]" ); # ------------------------------------------------------------------- # ======================================================================= def TEXT_CHANGED( self ): # ------------------------------------------------------------------- pass; #self.TEXT.setText( str(self.TEXT.toPlainText() ); #self.TEXT.setText( str(self.TEXT.text() ) ); # ------------------------------------------------------------------- # ======================================================================= def CMD( self, _CMD ): # ------------------------------------------------------------------- #__exec:notebook:notes:show" #__exec:notebook:notes:hide" #__exec:notebook:notes:keep_open:(0|1) # ------------------------------------------------------------------- try: # ----------------------------------------------- if _CMD[0] == "notes": if _CMD[1] == "show": self.SHOW_NOTES( ); elif _CMD[1] == "hide": self.HIDE_NOTES( ); elif _CMD[1] == "keep_open": self.KEEP_OPEN = True if _CMD[2] == "1" else False; self.LOCAL_INFO_LOG( "notebook:notes:keep_open:"+_CMD[2] ); return; # ----------------------------------------------- if _CMD[0] == "cmd": pass; # ----------------------------------------------- except Exception as _err: self.LOCAL_ERROR_LOG( str(_CMD)+" | "+str(_err) ); # ------------------------------------------------------------------- # ======================================================================= def SHOW_NOTES( self ): # ------------------------------------------------------------------- try: """ out = ""; for _key in self.LAST_PAGE_REQUEST_HEADERS: _l = "-----------------------------------------------------------------------\n"; _l += '["'+_key+'"] => \n["'+self.LAST_PAGE_REQUEST_HEADERS[ _key ]+'"]'+"\n"; print( "L: "+_l ); out += _l; self.TEXT.setText( out ); """ self.show(); self.IS_OPEN = True; self.TEXT.setFocus( True ); except Exception as _err: self.LOCAL_ERROR_LOG( "'Can't show notes: "+str(_err) ); # ------------------------------------------------------------------- # ======================================================================= def HIDE_NOTES( self ): # ------------------------------------------------------------------- self.hide(); self.IS_OPEN = False; self.TEXT.clearFocus(); # ------------------------------------------------------------------- # ======================================================================= def UPDATE_FRAME(self): # ------------------------------------------------------------------- return; # ------------------------------------------------------------------- """ try: _style = ""; _conf = []; with open( "./ALPHA_FRAME.conf" ) as FS: _conf = FS.readline(); print(_conf ); _conf = _conf.split("|"); self.setGeometry( int(_conf[0]), int(_conf[1]), int(_conf[2]), int(_conf[3]) ); for _line in FS: _style += _line; self.setStyleSheet( _style ); except Exception as _err: print("ERROR: "+str(_err)); self.UPDATE_TIMER.singleShot( 1000, self.UPDATE_FRAME ); """ # ------------------------------------------------------------------- # ======================================================================= def LOAD(self): # ------------------------------------------------------------------- if self.DEBUG: pass; # ------------------------------------------------------------------- try: # --------------------------------------------------- self.PARENT.SPLASH.STATUS( self.LOG_TAG+": [LOAD]" ); self.PARENT.LOG_HANDLER.WRITE_LOG( "Doc-Browser: NOTEBOOK: LODE: "); self.TEXT.clear(); with open( self.NOTEBOOK_FILE, "r") as FS: for line in FS: self.TEXT.append(line.strip()); #self.TEXT.insertPlainText(line); #self.TEXT.insertHtml(line); self.PARENT.LOG_HANDLER.WRITE_LOG( "Doc-Browser: NOTEBOOK: LODE: Done"); # --------------------------------------------------- except Exception as _err: self.LOCAL_ERROR_LOG( "Can't load notes: "+str(_err) ); # ------------------------------------------------------------------- # ======================================================================= def SAVE(self): # ------------------------------------------------------------------- if self.DEBUG: pass; # ------------------------------------------------------------------- try: # --------------------------------------------------- self.PARENT.LOG_HANDLER.WRITE_LOG( "Doc-Browser: NOTEBOOK: SAVE: "); DATA = str(self.TEXT.toPlainText()).split("\n"); with open( self.NOTEBOOK_FILE, "w") as FS: for line in DATA: FS.write( line+"\n" ); self.PARENT.LOG_HANDLER.WRITE_LOG( "Doc-Browser: NOTEBOOK: SAVE: Done"); # --------------------------------------------------- except Exception as _err: self.LOCAL_ERROR_LOG( "Can't save notes: "+str(_err) ); # ------------------------------------------------------------------- # ======================================================================= def LOCAL_INFO_LOG( self, _msg, METHOD=None ): # ------------------------------------------------------------------- if METHOD is None: self.PARENT.LOCAL_INFO_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" ); else: self.PARENT.LOCAL_INFO_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" ); # ------------------------------------------------------------------- # ======================================================================= def LOCAL_ERROR_LOG( self, _msg, METHOD=None ): # ------------------------------------------------------------------- if self.DEBUG or self.PARENT.DEBUG_GLOBAL: self.PARENT.DEBUGGER.DEBUG(); # ------------------------------------------------------------------- if METHOD is None: self.PARENT.LOCAL_ERROR_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" ); else: self.PARENT.LOCAL_ERROR_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" ); # ------------------------------------------------------------------- # ======================================================================= def LOCAL_WARNING_LOG( self, _msg, METHOD=None ): # ------------------------------------------------------------------- if METHOD is None: self.PARENT.LOCAL_WARNING_LOG( "['"+self.LOG_TAG+"']: ["+_msg+"]" ); else: self.PARENT.LOCAL_WARNING_LOG( "['"+self.LOG_TAG+"."+METHOD+"']: ["+_msg+"]" );
class HAConfigFrontend(FullFeaturedScrollArea): COMPONENT = 'ha' LABEL = tr('High Availability') REQUIREMENTS = ('ha',) ICON = ':/icons/picto_ha.png' if EDENWALL: LINK_STATE = { NOT_REGISTERED: tr('Not registered'), NOT_CONNECTED: tr('Not connected'), CONNECTED: tr('Connected'), } NODE_STATE = { NOT_REGISTERED: tr('Not registered'), ACTIVE: tr('Active'), INACTIVE: tr('Inactive'), } STATE_DESCRIPTIONS = { ENOHA: span(tr('High availability is not configured.')), PENDING_PRIMARY: span(tr('Primary; click "Join" to <br/>complete high availability configuration.')), PRIMARY: span(tr('Primary, in function.')), SECONDARY: span(tr('Secondary, in function.')), PENDING_SECONDARY: span(tr('Secondary; connect EAS to the primary server to <br/>complete high availability configuration.')), } def __init__(self, client, parent): self.auth_page = None self.group_page = None self.auth_configs = {} self.group_configs = {} self.mainwindow = parent self.node_status_label = QLabel() # status of current node (active / inactive) self.link_status_label = QLabel() # status of dedicaced link self.interface_label = QLabel() self.activity_label = QLabel() self.last_error_text = QTextEdit() self.last_error_text.setReadOnly(True) self.last_error_text.setMaximumHeight(100) self.type_label = QLabel() self.join = None self.link_state = None self.ha_last_date = None self.version = self.mainwindow.init_call('ha', 'getComponentVersion') FullFeaturedScrollArea.__init__(self, client, parent) self.missing_upgrades = [] # create timer only if HA activated if self.__ha_type() != ENOHA: self.timer = Timer( self.setViewData, REFRESH_INTERVAL_MILLISECONDS, self.mainwindow.keep_alive.thread, self ) else: self.timer = None self.force_join = QAction(QIcon(":/icons/force_join"), tr("Force joining secondary"), self) self.connect(self.force_join, SIGNAL('triggered(bool)'), self.joinSecondary) self.force_takeover = QAction(QIcon(":/icons/ha_takeover"), tr("Force to become active"), self) self.connect(self.force_takeover, SIGNAL('triggered(bool)'), self.takeover) buttons = [self.force_join, self.force_takeover] self.contextual_toolbar = ToolBar(buttons, name=tr("High Availability")) @staticmethod def get_calls(): """ services called by initial multicall """ return (('ha', 'getState'), ('ha', 'getFullState'), ('ha', 'getComponentVersion')) def __ha_type(self): config = QHAObject.getInstance().cfg if config is None: return ENOHA return config.ha_type def buildInterface(self): frame = QFrame() self.setWidget(frame) self.setWidgetResizable(True) layout = QGridLayout(frame) title = u'<h1>%s</h1>' % self.tr('High Availability Configuration') layout.addWidget(QLabel(title), 0, 0, 1, -1) configure = QPushButton(QIcon(":/icons/configurationha.png"), tr('Configure')) self.mainwindow.writeAccessNeeded(configure) layout.addWidget(configure, 1, 3) self.join = QPushButton(QIcon(":/icons/joinha.png"), tr('Join Secondary')) layout.addWidget(self.join, 2, 3) if "1.1" == self.version: layout.addWidget(QLabel(tr('Appliance status')), 3, 0) layout.addWidget(self.node_status_label, 3, 1) row = 4 else: row = 3 self.last_error_title = QLabel(tr('Last error')) self.missing_upgrade_text_label = QLabel() self.missing_upgrade_nums_label = QLabel() widgets = [ (QLabel(tr('Link status')), self.link_status_label), (QLabel(tr('Type')),self.type_label), (QLabel(tr('Interface')),self.interface_label), (QLabel(tr('Last activity')), self.activity_label), (self.last_error_title, self.last_error_text), (self.missing_upgrade_text_label, self.missing_upgrade_nums_label), ] for index, (label, widget) in enumerate(widgets): layout.addWidget(label, row+index, 0) layout.addWidget(widget, row+index, 1) # syncUpgrades_button = QPushButton(tr('Synchronize upgrades')) # layout.addWidget(syncUpgrades_button, 7, 2) # self.connect(syncUpgrades_button, SIGNAL('clicked()'), self.syncUpgrades) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 5) layout.setColumnStretch(2, 10) layout.setColumnStretch(3, 1) layout.setRowStretch(row+6, row+7) self.connect(configure, SIGNAL("clicked()"), self.displayConfig) self.connect(self.join, SIGNAL("clicked()"), self.joinSecondary) def displayConfig(self): config = QHAObject.getInstance().hacfg if config.ha_type == PRIMARY: QMessageBox.warning( self, tr('High availability already configured'), tr('High availability status disallows editing the configuration')) return ha_wizard = ConfigWizard(self) ret = ha_wizard.exec_() if ret != QDialog.Accepted: return False qhaobject = QHAObject.getInstance() qhaobject.pre_modify() config = qhaobject.hacfg qnetobject = QNetObject.getInstance() qnetobject.pre_modify() net_cfg = qnetobject.netcfg old_type = config.ha_type new_config = ha_wizard.getData() config.ha_type = new_config.ha_type config.interface_id = new_config.interface_id config.interface_name = new_config.interface_name if config.ha_type in (PENDING_PRIMARY, PENDING_SECONDARY): iface = net_cfg.getIfaceByHardLabel(config.interface_id) configureHA(net_cfg, iface) network_modified = True elif config.ha_type != old_type: deconfigureHA(net_cfg) network_modified = True # XXX should not reconfigure now ? else: network_modified = False valid = qnetobject.post_modify() if not valid: qhaobject.revert() else: # FIXME: use post_modify() result? qhaobject.post_modify() self.setModified(True) if network_modified: network = self.mainwindow.getPage('network') network.setModified(True) dhcp = self.mainwindow.getPage('dhcp') dhcp.dhcp_widget.setModified(True) dhcp.dhcp_widget.fillView() self.setViewData() return True def hide_last_error(self): self.last_error_text.clear() self.last_error_text.hide() self.last_error_title.hide() def show_last_error(self, last_error): if last_error: self.last_error_text.setText(last_error) self.last_error_title.show() self.last_error_text.show() else: self.hide_last_error() def syncUpgrades(self): # First, update the list of missing upgrades: defer = self.setViewData() if defer: defer.addCallback(self._syncUpgrades) def _syncUpgrades(self): pass def fetchConfig(self): # we use QHAObject pass def __disable(self): self.close() raise NuConfModuleDisabled("Disabling high availability interface") def setViewData(self): config = QHAObject.getInstance().hacfg if "1.0" == self.version: raw_state = self.mainwindow.init_call('ha', 'getState') if raw_state is None: self.__disable() return self.link_state, self.ha_last_date, last_error = raw_state self.link_status_label.setText(self.LINK_STATE.get(self.link_state, tr('(unknown)'))) else: raw_state = self.mainwindow.init_call('ha', 'getFullState') if raw_state is None: self.__disable() return node_state = raw_state['node_state'] self.link_state = raw_state['link_state'] self.ha_last_date = raw_state['seen_other'] last_error = raw_state['last_error'] self.link_status_label.setText(self.LINK_STATE.get(self.link_state, tr('(unknown)'))) self.node_status_label.setText(self.NODE_STATE.get(node_state, tr('(unknown)'))) # TEMP : use compatibility instead try: try: if raw_state.get('link_state', None) == CONNECTED: self.join.setEnabled(False) except Exception: if isinstance(raw_state, list) and len(raw_state) > 0: if raw_state[0] == CONNECTED: self.join.setEnabled(False) except TypeError: pass ha_type = self.__ha_type() self.type_label.setText( HAConfigFrontend.STATE_DESCRIPTIONS[ha_type] ) if ha_type != ENOHA: if self.ha_last_date not in (0, None): fmt = '%Y-%m-%d %H:%M:%S' seen = time.strftime(fmt, time.localtime(self.ha_last_date)) self.activity_label.setText(unicode(seen)) if config.interface_id is not None: qnetobject = QNetObject.getInstance() iface = qnetobject.netcfg.getIfaceByHardLabel(config.interface_id) self.interface_label.setText(iface.fullName()) try: last_error = self.client.call('ha', 'getLastError') self.show_last_error(last_error) except Exception: self.hide_last_error() else: self.interface_label.clear() self.activity_label.clear() self.hide_last_error() if ha_type == PRIMARY: async = self.client.async() async.call('ha', 'getMissingUpgradeNums', callback=self._get_missing_upgrade_nums, errback=self.writeError) self.mainwindow.writeAccessNeeded(self.join) if self.join.isEnabled(): self.join.setEnabled(PENDING_PRIMARY == ha_type) def _get_missing_upgrade_nums(self, missing_upgrade_nums): try: self.missing_upgrade_nums = missing_upgrade_nums if type(missing_upgrade_nums) != type([]): self.missing_upgrade_nums_label.setText(tr('N/A')) elif not missing_upgrade_nums: self.missing_upgrade_nums_label.setText(tr('None ')) else: sample = sorted(missing_upgrade_nums) if len(sample) > MAX_MISSING_UPGRADE_NUMS: sample = sample[:MAX_MISSING_UPGRADE_NUMS] + ['...'] self.missing_upgrade_nums_label.setText( ', '.join([unicode(num) for num in sample])) self.missing_upgrade_text_label.setText( tr('Missing upgrades on the secondary')) except Exception: pass def sendConfig(self, message): """ Save HA config """ serialized = QHAObject.getInstance().hacfg.serialize() self.client.call('ha', 'configureHA', serialized, message) def joinSecondary(self): self.mainwindow.addToInfoArea( tr("Attempting to enslave the secondary, please wait...") ) self.splash = SplashScreen() self.splash.setText(tr("Attempting to enslave the secondary...")) self.splash.show() async = self.client.async() async.call('ha', 'startHA', callback = self.successJoin, errback = self.errorJoin ) def successJoin(self, ok): self.splash.hide() self.timer = Timer( self.setViewData, REFRESH_INTERVAL_MILLISECONDS, self.mainwindow.keep_alive.thread, self ) self.join.setEnabled(False) self.mainwindow.addToInfoArea(tr("Joining secondary: success"), category=COLOR_SUCCESS) def errorJoin(self, error): self.splash.hide() self.mainwindow.addToInfoArea(tr('Joining secondary: fail'), category=COLOR_ERROR) warning = QMessageBox(self) warning.setWindowTitle(tr('Joining secondary: fail')) warning.setText(tr('An error was encountered while joining secondary.')) errmsg = exceptionAsUnicode(error) if "current state=ENOHA" in errmsg: errmsg = tr( "Can not join yet: the appliance is still not configured for " "high availability. Did you save and apply your changes?" ) warning.setDetailedText(errmsg) warning.setIcon(QMessageBox.Warning) warning.exec_() def takeover(self): try: self.client.call('ha', 'takeover') except Exception, err: self.mainwindow.exception(err) return self.mainwindow.addToInfoArea(tr('Take over request sent.'), category=COLOR_SUCCESS)
class AddWordWidget(QDialog): def __init__(self, parent=None): super(AddWordWidget, self).__init__(parent=parent) self.setWindowTitle('Add word') self.create_layout() self.create_connections() def create_layout(self): hbox = QHBoxLayout() vbox = QVBoxLayout() vbox.addWidget(QLabel("Dictionary")) vbox.addWidget(QLabel("Original")) vbox.addWidget(QLabel("Translation")) vbox.addWidget(QLabel("Phoneme")) vbox.addWidget(QLabel("Parts of Speech")) vbox.addWidget(QLabel("Synonyms")) vbox.addWidget(QLabel("Antonyms")) hbox.addLayout(vbox) vbox = QVBoxLayout() self.dictionaries = Dictionary.objects.all() self.dictionary = QComboBox() self.dictionary.addItems([d.name for d in self.dictionaries]) vbox.addWidget(self.dictionary) self.original = QLineEdit() vbox.addWidget(self.original) self.translation = QLineEdit() vbox.addWidget(self.translation) self.phoneme = QLineEdit() vbox.addWidget(self.phoneme) self.pos = QComboBox() self.pos.addItems([p.strip() for p in self.dictionaries[0].pos.split(',') if len(p) > 0]) vbox.addWidget(self.pos) self.synonyms = QLineEdit() vbox.addWidget(self.synonyms) self.antonyms = QLineEdit() vbox.addWidget(self.antonyms) hbox.addLayout(vbox) vbox = QVBoxLayout() vbox.addLayout(hbox) vbox.addWidget(QLabel("Description")) self.description = QTextEdit() vbox.addWidget(self.description) self.add_button = QPushButton("&Add") self.close_button = QPushButton("&Close") hbox = QHBoxLayout() hbox.addStretch() hbox.addWidget(self.add_button) hbox.addWidget(self.close_button) vbox.addLayout(hbox) self.status = QLabel('Add a new word to a dictionary.') vbox.addWidget(self.status) self.setLayout(vbox) def create_connections(self): self.connect(self.dictionary, SIGNAL("currentIndexChanged(int)"), self.change_pos) self.connect(self.close_button, SIGNAL("clicked()"), self.close) self.connect(self.add_button, SIGNAL("clicked()"), self.add_word) def change_pos(self, index): current_dict = self.dictionaries[index] self.pos.clear() self.pos.addItems([p.strip() for p in current_dict.pos.split(',') if len(p) > 0]) def get_texts(self): current_dict = self.dictionaries[self.dictionary.currentIndex()].abbrev original = unicode(self.original.text()).strip() translation = unicode(self.translation.text()).strip() phoneme = unicode(self.phoneme.text()).strip() pos = unicode(self.pos.currentText()).strip() synonyms = unicode(self.synonyms.text()).strip() antonyms = unicode(self.antonyms.text()).strip() description = unicode(self.description.toPlainText()).strip() if not all([original, translation, pos]): self.status.setText('There was an error inserting the word. Please' ' try again.') QMessageBox.critical(self, "Error", "You must enter at least " "'Original', 'Translation' and 'Parts of " "Speech'.") return None return dict(dictionary=current_dict, original=original, translation=translation, phoneme=phoneme, pos=pos, synonyms=synonyms, antonyms=antonyms, description=description) def clear_texts(self): self.translation.clear() self.phoneme.clear() self.synonyms.clear() self.antonyms.clear() self.description.clear() self.original.setFocus() def add_word(self): self.status.clear() texts = self.get_texts() if not texts: return word = Word(**texts) word.save() self.clear_texts() self.status.setText('Word %s has been added successfully.' % word.original) self.words_widget.load_words() def save_word(self): self.status.clear() texts = self.get_texts() if not texts: return word = self.word word.dictionary = texts['dictionary'] word.original = texts['original'] word.translation = texts['translation'] word.phoneme = texts['phoneme'] word.pos = texts['pos'] word.synonyms = texts['synonyms'] word.antonyms = texts['antonyms'] word.description = texts['description'] word.save() self.status.setText('Word %s has been saved successfully' % word.original) self.words_widget.load_words() def get_word(self): return self._word def set_word(self, word): self._word = word self.setWindowTitle("Edit %s" % word.original) self.add_button.setText("&Save") self.disconnect(self.add_button, SIGNAL("clicked()"), self.add_word) if word.exported: self.add_button.setEnabled(False) self.status.setText('This word has been exported already. ' 'You cannot save the changes to it.') else: self.connect(self.add_button, SIGNAL("clicked()"), self.save_word) self.status.setText('Edit this word and save to your dictionary.') for i, d in enumerate(self.dictionaries): if d.abbrev == word.dictionary: self.dictionary.setCurrentIndex(i) break self.original.setText(word.original) self.translation.setText(word. translation) self.phoneme.setText(word.phoneme) self.synonyms.setText(word.synonyms) self.antonyms.setText(word.antonyms) self.description.setText(word.description) for i in range(self.pos.count()): if self.pos.itemText(i) == word.pos: self.pos.setCurrentIndex(i) break word = property(get_word, set_word)
class OnlineUpdateGUI(QWidget): CHECK_INTERVAL = 12 * 60 * 60 * 1000 # check twice a day checkForAppUpdate = pyqtSignal() checkForRepoUpdates = pyqtSignal() installUpdates = pyqtSignal() def __init__(self, installedVersion, parent): super(OnlineUpdateGUI, self).__init__(parent) self._canCheckForAppUpdate = False self._canCheckForRepoUpdate = False self._appUpdatesAvailable = False self._repoUpdatesAvailable = False layout = QVBoxLayout(self) layout.addWidget(self._createAppUpdateWidget(installedVersion)) layout.addWidget(self._createRepoUpdateWidget()) self._installUpdatesButton = QPushButton("Install Update(s) and Restart", self) self._installUpdatesButton.clicked.connect(self.installUpdates) self._installUpdatesButton.setEnabled(False) layout.addWidget(self._installUpdatesButton) self._spacing = QWidget(self) layout.addWidget(self._spacing, 1) self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) def _createAppUpdateWidget(self, installedVersion): widget = QGroupBox("Application", self) layout = QVBoxLayout(widget) versionLabel = QLabel("Installed Version: " + installedVersion) layout.addWidget(versionLabel, 0) self._appStatusLabel = QLabel(widget) self._appStatusLabel.setWordWrap(True) layout.addWidget(self._appStatusLabel, 0) self._progressBar = QProgressBar(widget) self._progressBar.setVisible(False) layout.addWidget(self._progressBar, 0) self._appCheckButton = QPushButton("Check for Update", widget) self._appCheckButton.clicked.connect(self.checkForAppUpdate) layout.addWidget(self._appCheckButton, 0) self._appChangeLog = QTextEdit(self) self._appChangeLog.setReadOnly(True) self._appChangeLog.setVisible(False) layout.addWidget(self._appChangeLog, 1) return widget def _createRepoUpdateWidget(self): widget = QGroupBox("Plugin Repositories", self) layout = QVBoxLayout(widget) self._repoStatusLabel = QLabel(widget) layout.addWidget(self._repoStatusLabel) self._repoCheckButton = QPushButton("Check for Updates", widget) self._repoCheckButton.clicked.connect(self.checkForRepoUpdates) layout.addWidget(self._repoCheckButton) return widget def setChangelogVisible(self, v): self._appChangeLog.setVisible(v) self._spacing.setVisible(not v) def setProgress(self, prog): self._progressBar.setValue(prog) def setProgressIndeterminate(self, indeterminate): self._progressBar.setMaximum(0 if indeterminate else 100) def setCheckAppUpdateButtonText(self, text=None): if not text: text = "Check for Update" self._appCheckButton.setText(text) def setInteractive(self, interactive): if interactive: self._appCheckButton.setEnabled(self._canCheckForAppUpdate) self._repoCheckButton.setEnabled(self._canCheckForRepoUpdate) self._installUpdatesButton.setEnabled(self._appUpdatesAvailable or self._repoUpdatesAvailable) else: self._appCheckButton.setEnabled(False) self._repoCheckButton.setEnabled(False) self._installUpdatesButton.setEnabled(False) def setCanCheckForAppUpdate(self, can): self._canCheckForAppUpdate = can self._appCheckButton.setEnabled(can) def setCanCheckForRepoUpdate(self, can): self._canCheckForRepoUpdate = can self._repoCheckButton.setEnabled(can) def appInstallReady(self): self._appUpdatesAvailable = True self._installUpdatesButton.setEnabled(True) def setRepoUpdatesAvailable(self, avail): self._repoUpdatesAvailable = True self._installUpdatesButton.setEnabled(avail or self._appUpdatesAvailable) def setRepoStatus(self, status): self._repoStatusLabel.setText(status) def setAppStatus(self, status, progress=False): self._progressBar.setVisible(progress) self._appStatusLabel.setText(status) def setAppStatusToolTip(self, text): self._appStatusLabel.setToolTip(text) def setAppChangeLog(self, log): self._appChangeLog.clear() document = self._appChangeLog.document() document.setIndentWidth(20) cursor = QTextCursor(document) cursor.insertText("Changes:\n") listFormat = QTextListFormat() listFormat.setStyle(QTextListFormat.ListDisc) listFormat2 = QTextListFormat() listFormat2.setStyle(QTextListFormat.ListDisc) listFormat2.setIndent(2) for line in log: if line.startswith("*"): cursor.insertList(listFormat2) line = line[1:] else: cursor.insertList(listFormat) cursor.insertText(line) self.setChangelogVisible(True)
class DHttpReplay(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ Http replay dialog """ def __init__(self, parent=None, offlineMode=False): """ Constructor @param parent: @type parent: """ super(DHttpReplay, self).__init__(parent) self.offlineMode = offlineMode self.defaultIp = "127.0.0.1" self.defaultPort = "80" self.newTest = '' self.newTestExec = '' self.newInputs = [] self.requests = [] self.responses = [] self.defaultTemplates = DefaultTemplates.Templates() self.testType = None self.createDialog() self.createConnections() self.createActions() self.createToolbar() def createActions(self): """ Create qt actions """ self.openAction = QtHelper.createAction(self, "&Open", self.importTrace, icon=QIcon(":/folder_add.png"), tip='Open network trace.') self.exportTUAction = QtHelper.createAction( self, "&Test Unit", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to Test Unit') self.exportTSAction = QtHelper.createAction( self, "&Test Suite", self.exportToTS, icon=QIcon(":/%s.png" % WWorkspace.TestSuite.TYPE), tip='Export to Test Suite') self.cancelAction = QtHelper.createAction(self, "&Cancel", self.reject, tip='Cancel') menu = QMenu(self) menu.addAction(self.exportTUAction) menu.addAction(self.exportTSAction) self.exportToAction = QtHelper.createAction( self, "&Export to", self.exportToTU, icon=QIcon(":/%s.png" % WWorkspace.TestUnit.TYPE), tip='Export to tests') self.exportToAction.setMenu(menu) self.exportToAction.setEnabled(False) def createDialog(self): """ Create dialog """ self.dockToolbar = QToolBar(self) self.dockToolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.setWindowTitle(WINDOW_TITLE) self.resize(500, 400) self.ipEdit = QLineEdit(self.defaultIp) ipRegExpVal = QRegExpValidator(self) ipRegExp = QRegExp("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") ipRegExpVal.setRegExp(ipRegExp) self.ipEdit.setValidator(ipRegExpVal) self.portEdit = QLineEdit(self.defaultPort) self.portEdit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) validatorPort = QIntValidator(self) self.portEdit.setValidator(validatorPort) self.progressBar = QProgressBar(self) self.progressBar.setMaximum(100) self.progressBar.setProperty("value", 0) self.progressBar.setAlignment(Qt.AlignCenter) self.progressBar.setObjectName("progressBar") self.guiSikuliGroupBox = QGroupBox("") self.guiSikuliGroupBox.setFlat(True) self.automaticAdp = QRadioButton("Automatic") self.automaticAdp.setChecked(True) self.defaultAdp = QRadioButton("Default") self.genericAdp = QRadioButton("Generic") vbox = QHBoxLayout() vbox.addWidget(self.automaticAdp) vbox.addWidget(self.defaultAdp) vbox.addWidget(self.genericAdp) vbox.addStretch(1) self.guiSikuliGroupBox.setLayout(vbox) layout = QVBoxLayout() layout.addWidget(self.dockToolbar) layout.addSpacing(12) paramLayout = QGridLayout() paramLayout.addWidget(QLabel("Destination IP:"), 0, 0, Qt.AlignRight) paramLayout.addWidget(self.ipEdit, 0, 1) paramLayout.addWidget(QLabel("Destination Port:"), 1, 0, Qt.AlignRight) paramLayout.addWidget(self.portEdit, 1, 1) paramLayout.addWidget(QLabel(self.tr("Gui adapter selector:")), 2, 0, Qt.AlignRight) paramLayout.addWidget(self.guiSikuliGroupBox, 2, 1) layout.addLayout(paramLayout) self.logsEdit = QTextEdit() self.logsEdit.setReadOnly(True) self.logsEdit.setTextInteractionFlags(Qt.NoTextInteraction) layout.addSpacing(12) layout.addWidget(self.logsEdit) layout.addSpacing(12) layout.addWidget(self.progressBar) self.setLayout(layout) def createToolbar(self): """ Create toolbar """ self.dockToolbar.setObjectName("File toolbar") self.dockToolbar.addAction(self.openAction) self.dockToolbar.addSeparator() self.dockToolbar.addAction(self.exportToAction) self.dockToolbar.addSeparator() self.dockToolbar.setIconSize(QSize(16, 16)) def createConnections(self): """ Create qt connections """ pass def autoScrollOnTextEdit(self): """ Automatic scroll on text edit """ cursor = self.logsEdit.textCursor() cursor.movePosition(QTextCursor.End) self.logsEdit.setTextCursor(cursor) def strip_html(self, txt): """ Strip html """ if "<" in txt: txt = txt.replace('<', '<') if ">" in txt: txt = txt.replace('>', '>') return txt def addLogSuccess(self, txt): """ Add log success in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkgreen'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogWarning(self, txt): """ Add log warning in the text edit """ self.logsEdit.insertHtml( "<span style='color:darkorange'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLogError(self, txt): """ Add log error in the text edit """ self.logsEdit.insertHtml("<span style='color:red'>%s</span><br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def addLog(self, txt): """ Append log to the logsEdit widget """ self.logsEdit.insertHtml("%s<br />" % unicode(self.strip_html(txt))) self.autoScrollOnTextEdit() def importTrace(self): """ Import network trace """ self.logsEdit.clear() self.testType = None if not self.offlineMode: if not RCI.instance().isAuthenticated(): self.addLogWarning( txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return self.exportToAction.setEnabled(False) self.newTest = '' self.progressBar.setMaximum(100) self.progressBar.setValue(0) if sys.version_info > (3, ): fileName = QFileDialog.getOpenFileName( self, self.tr("Open File"), "", "Network dump (*.cap;*.pcap;*.pcapng)") else: fileName = QFileDialog.getOpenFileName(self, self.tr("Open File"), "", "Network dump (*.cap)") # new in v18 to support qt5 if QtHelper.IS_QT5: _fileName, _type = fileName else: _fileName = fileName # end of new if not _fileName: return if sys.version_info < (3, ): extension = str(_fileName).rsplit(".", 1)[1] if not (extension == "cap"): self.addLogError(txt="<< File not supported %s" % _fileName) QMessageBox.critical(self, "Open", "File not supported") return _fileName = str(_fileName) capName = _fileName.rsplit("/", 1)[1] self.addLogSuccess(txt=">> Reading the file %s" % _fileName) if sys.version_info > (3, ): self.readFileV2(fileName=_fileName) else: self.readFile(fileName=_fileName) def exportToTS(self): """ Export to test suite """ self.testType = TS self.exportToTest(TS=True, TU=False) def exportToTU(self): """ Export to test unit """ self.testType = TU self.exportToTest(TS=False, TU=True) def searchHTTP(self): """ Search HTTP module in assistant """ # modules accessor ret = "SutAdapters" if self.automaticAdp.isChecked(): isGeneric = WWorkspace.Helper.instance().isGuiGeneric(name="GUI") if isGeneric: ret = "SutAdapters.Generic" elif self.defaultAdp.isChecked(): return ret elif self.genericAdp.isChecked(): ret = "SutAdapters.Generic" else: pass return ret def exportToTest(self, TS=True, TU=False): """ Export to test """ if not RCI.instance().isAuthenticated(): self.addLogWarning(txt="<< Connect to the test center in first!") QMessageBox.warning(self, "Import", "Connect to the test center in first!") return if TS: self.newTest = self.defaultTemplates.getTestDefinitionAuto() self.newTestExec = self.defaultTemplates.getTestExecutionAuto() if TU: self.newTest = self.defaultTemplates.getTestUnitDefinitionAuto() destIp = str(self.ipEdit.text()) destPort = str(self.portEdit.text()) self.newInputs = [] self.newInputs.append({ 'type': 'self-ip', 'name': 'BIND_IP', 'description': '', 'value': '0.0.0.0', 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'BIND_PORT', 'description': '', 'value': '0', 'color': '' }) self.newInputs.append({ 'type': 'str', 'name': 'DEST_IP', 'description': '', 'value': '%s' % destIp, 'color': '' }) self.newInputs.append({ 'type': 'int', 'name': 'DEST_PORT', 'description': '', 'value': '%s' % destPort, 'color': '' }) self.newInputs.append({ 'type': 'bool', 'name': 'DEBUG', 'description': '', 'value': 'False', 'color': '' }) self.newInputs.append({ 'type': 'float', 'name': 'TIMEOUT', 'description': '', 'value': '5.0', 'color': '' }) adps = """self.ADP_HTTP = %s.HTTP.Client(parent=self, bindIp=input('BIND_IP'), bindPort=input('BIND_PORT'), destinationIp=input('DEST_IP'), destinationPort=input('DEST_PORT'), debug=input('DEBUG'))""" % self.searchHTTP( ) # prepare steps steps = [] j = 0 for i in xrange(len(self.requests)): j = i + 1 if sys.version_info > (3, ): # python3 support (source, dest, source_port, dest_port, buf_req, reqDecoded) = self.requests[i] http_method = str(reqDecoded['method'], 'utf8') http_status = 'no' http_reason = '' else: http_method = self.requests[i]['tcp-object'].method http_status = 'no' http_reason = '' try: if sys.version_info > (3, ): # python3 support (sourceRsp, destRsp, sourcePortRsp, destPortRsp, bufReqRsp, reqDecodedRsp) = self.responses[i] http_status = str(reqDecodedRsp['code']) http_reason = str(reqDecodedRsp['phrase'], 'utf8') else: http_status = self.responses[i]['tcp-object'].status http_reason = self.responses[i]['tcp-object'].reason except Exception as e: print(e) steps.append( 'self.step%s = self.addStep(expected="%s %s response", description="send %s request", summary="send %s request")' % (j, http_status, http_reason, http_method, http_method)) tests = [] for i in xrange(len(self.requests)): j = i + 1 if sys.version_info > (3, ): # python3 support (source, dest, source_port, dest_port, buf_req, reqDecoded) = self.requests[i] tests.append("# request %s" % j) tests.append('self.step%s.start()' % j) if sys.version_info > (3, ): # python3 support lines_req = buf_req.splitlines() else: lines_req = self.requests[i]['tcp-data'].splitlines() if sys.version_info > (3, ): # python3 support tests.append('rawHttp = [%s]' % lines_req[0].replace(b'"', b'\\"')) else: tests.append('rawHttp = ["%s"]' % lines_req[0].replace(b'"', b'\\"')) for lreq in lines_req[1:]: if sys.version_info > (3, ): # python3 support tests.append('rawHttp.append(%s)' % lreq.replace(b'"', b'\\"')) else: tests.append('rawHttp.append("%s")' % lreq.replace(b'"', b'\\"')) tests.append('') tests.append( 'req_tpl = self.ADP_HTTP.constructTemplateRequest(rawHttp=rawHttp)' ) tests.append('req = self.ADP_HTTP.sendRequest(tpl=req_tpl)') try: tests.append('') if sys.version_info > (3, ): # python3 support (sourceRsp, destRsp, sourcePortRsp, destPortRsp, bufReqRsp, reqDecodedRsp) = self.responses[i] lines_res = bufReqRsp.splitlines() else: lines_res = self.responses[i]['tcp-data'].splitlines() if sys.version_info > (3, ): # python3 support tests.append('rawHttpRsp = [%s]' % lines_res[0].replace(b"'", b"\\'")) else: tests.append('rawHttpRsp = ["%s"]' % lines_res[0].replace(b'"', b'\\"')) for lres in lines_res[1:]: if sys.version_info > (3, ): # python3 support tests.append('rawHttpRsp.append(%s)' % lres.replace(b"'", b"\\'")) else: tests.append('rawHttpRsp.append("%s")' % lres.replace(b'"', b'\\"')) except Exception as e: self.error("unable to append response: %s" % e) tests.append( 'rsp_tpl = self.ADP_HTTP.constructTemplateResponse(rawHttp=rawHttpRsp)' ) tests.append( "rsp = self.ADP_HTTP.hasReceivedResponse(expected=rsp_tpl, timeout=input('TIMEOUT'))" ) tests.append('if rsp is None:') tests.append( '\tself.step%s.setFailed(actual="incorrect response")' % j) tests.append('else:') tests.append('\tself.step%s.setPassed(actual="ok")' % j) tests.append('') if TS: init = """self.ADP_HTTP.connect() connected = self.ADP_HTTP.isConnected( timeout=input('TIMEOUT') ) if not connected: self.abort( 'unable to connect to the tcp port %s' ) """ % str(self.portEdit.text()) if TU: init = """self.ADP_HTTP.connect() connected = self.ADP_HTTP.isConnected( timeout=input('TIMEOUT') ) if not connected: self.abort( 'unable to connect to the tcp port %s' ) """ % str(self.portEdit.text()) if TS: cleanup = """self.ADP_HTTP.disconnect() disconnected = self.ADP_HTTP.isDisconnected( timeout=input('TIMEOUT') ) if not disconnected: self.error( 'unable to disconnect from the tcp port %s' ) """ % str(self.portEdit.text()) if TU: cleanup = """self.ADP_HTTP.disconnect() disconnected = self.ADP_HTTP.isDisconnected( timeout=input('TIMEOUT') ) if not disconnected: self.error( 'unable to disconnect from the tcp port %s' ) """ % str(self.portEdit.text()) self.newTest = self.newTest.replace( "<<PURPOSE>>", 'self.setPurpose(purpose="Replay HTTP")') self.newTest = self.newTest.replace("<<ADPS>>", adps) if TS: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t\t'.join(steps)) if TU: self.newTest = self.newTest.replace("<<STEPS>>", '\n\t'.join(steps)) self.newTest = self.newTest.replace("<<INIT>>", init) self.newTest = self.newTest.replace("<<CLEANUP>>", cleanup) if TS: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t\t'.join(tests)) if TU: self.newTest = self.newTest.replace("<<TESTS>>", '\n\t'.join(tests)) self.accept() def decodeHttpRequest(self, data): """ Decode http request Content chunked not yet implemented """ http = {"type": "request"} lines = data.splitlines() try: request_line = lines[0] except Exception: self.error("unable to decode http request: %s" % lines) return None try: http["method"] = request_line.split(b" ", 2)[0] http["uri"] = request_line.split(b" ", 2)[1] http["version"] = request_line.split(b" ", )[2] except Exception: self.error( "unable to decode status code in the http response: %s" % request_line) return None http["body"] = data.split(b"\r\n\r\n")[1] headers = [] contentLenght = 0 contentChunked = False for hdr in data.split(b"\r\n\r\n")[0].splitlines()[1:]: if len(hdr): k, v = hdr.split(b":", 1) if k.lower() == b"content-length": contentLenght = int(v) if k.lower() == b"transfer-encoding": if v.lowert() == b"chunked": contentChunked = True headers.append(hdr) http["headers"] = headers if len(http["body"]) != contentLenght: return None # need more data return http def decodeHttpResponse(self, data): """ Decode http response without body """ http = {"type": "response"} lines = data.splitlines() try: status_line = lines[0] except Exception: self.error("unable to decode http response: %s" % lines) return None try: http["code"] = int(status_line.split(b" ")[1]) http["phrase"] = status_line.split(b" ", 2)[2] except Exception: self.error( "unable to decode status code in the http response: %s" % status_line) return None http["headers"] = lines[1:] return http def readFileV2(self, fileName): """ Read pcap file Support pcap-ng too """ fd = open(fileName, 'rb') fileFormat, fileHead = PcapParse.extractFormat(fd) if fileFormat == PcapParse.FileFormat.PCAP: self.trace("pcap file detected") pcapFile = PcapReader.PcapFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) elif fileFormat == PcapParse.FileFormat.PCAP_NG: self.trace("pcap-png file detected") pcapFile = PcapngReader.PcapngFile(fd, fileHead).read_packet self.readFilePacket(pcapFile=pcapFile) else: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: file format = %s' % fileFormat) QMessageBox.critical(self, "Import", "File not supported") def __readRequest(self, buffer, data, request, output): """ Read request """ buffer += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buffer) if reqDecoded is not None: output.append(request + (reqDecoded, )) buffer = b'' else: print("need more data: decode request failed") else: print("need more data, no body separator detected on request") def readFilePacket(self, pcapFile): """ Read file packet by packet """ ip_expected = str(self.ipEdit.text()) port_expected = int(self.portEdit.text()) # read packet) packets = pcapFile() ethernetPackets = list(packets) self.addLogSuccess(txt="<< Number of packets detected: %s " % len(ethernetPackets)) # extract tcp packet according to the expected ip and port tcpPacketsSent = [] tcpPacketsRecv = [] i = 1 self.progressBar.setMaximum(len(ethernetPackets)) self.progressBar.setValue(0) for pkt in ethernetPackets: self.progressBar.setValue(i) i += 1 pktDecoded = PcapParse.decodePacket(pkt, getTcp=True, getUdp=False) if pktDecoded is not None: (source, dest, source_port, dest_port, data) = pktDecoded # skip when no data exists if dest == ip_expected and int(dest_port) == int( port_expected) and len(data) > 0: tcpPacketsSent.append(pktDecoded) if source == ip_expected and int(source_port) == int( port_expected) and len(data) > 0: tcpPacketsRecv.append(pktDecoded) self.addLogSuccess(txt="<< Number of TCP packets sent: %s " % len(tcpPacketsSent)) self.addLogSuccess(txt="<< Number of TCP packets received: %s " % len(tcpPacketsRecv)) # decode https requests self.requests = [] buf_req = b'' i = 1 self.progressBar.setMaximum(len(tcpPacketsSent)) self.progressBar.setValue(0) # decode the complete packet for req in tcpPacketsSent: self.progressBar.setValue(i) i += 1 (source, dest, source_port, dest_port, data) = req if buf_req: buf_req += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buf_req) if reqDecoded is not None: self.requests.append((source, dest, source_port, dest_port, buf_req, reqDecoded)) buf_req = b'' else: if isRequest(data): buf_req += data if b'\r\n\r\n' in data: reqDecoded = self.decodeHttpRequest(data=buf_req) if reqDecoded is not None: self.requests.append( (source, dest, source_port, dest_port, buf_req, reqDecoded)) buf_req = b'' self.addLogSuccess(txt="<< Number of HTTP requests extracted: %s " % len(self.requests)) # decode https response self.responses = [] buf_rsp = b'' i = 1 self.progressBar.setMaximum(len(tcpPacketsRecv)) self.progressBar.setValue(0) # decode just headers for response for req in tcpPacketsRecv: self.progressBar.setValue(i) i += 1 (source, dest, source_port, dest_port, data) = req if buf_rsp: buf_rsp += data # try to decode response without body if b'\r\n\r\n' in data: rspDecoded = self.decodeHttpResponse(data=buf_rsp) if rspDecoded is not None: self.responses.append((source, dest, source_port, dest_port, buf_rsp, rspDecoded)) buf_rsp = b'' else: # is http response ? if data.startswith(b'HTTP/'): buf_rsp += data if b'\r\n\r\n' in data: rspDecoded = self.decodeHttpResponse(data=buf_rsp) if rspDecoded is not None: self.responses.append( (source, dest, source_port, dest_port, buf_rsp, rspDecoded)) buf_rsp = b'' self.addLogSuccess(txt="<< Number of HTTP responses extracted: %s " % len(self.responses)) if self.requests: self.addLogSuccess("<< Read the file finished with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No http extracted!") def readFile(self, fileName): """ Read the file passed as argument Old function with dtpkt and python2.7 """ self.requests = [] self.responses = [] ip_expected = socket.inet_aton(str(self.ipEdit.text())) port_expected = str(self.portEdit.text()) try: f = open(fileName, 'rb') pcap = dpkt.pcap.Reader(f) tot_pkts = len(list(pcap)) except Exception as e: self.addLogError(txt="<< Error to open the network trace") self.error('unable to open the network trace: %s' % str(e)) QMessageBox.critical(self, "Import", "File not supported") return else: self.addLogSuccess(txt="<< Total packets detected: %s " % tot_pkts) self.progressBar.setMaximum(tot_pkts) # decode http request i = 1 buf_req = '' for ts, buf in pcap: self.progressBar.setValue(i) i += 1 # read ethernet layer eth = dpkt.ethernet.Ethernet(buf) if eth.type == dpkt.ethernet.ETH_TYPE_IP: # continue with ip decoding layer ip = eth.data if ip.dst == ip_expected: ip_layer = (ip.src, ip.dst) if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data if tcp.dport == int(port_expected) and len( tcp.data) > 0: tcp_layer = (tcp.sport, tcp.dport) buf_req += tcp.data try: http_req = dpkt.http.Request(buf_req) except dpkt.dpkt.NeedData as e: pass except dpkt.UnpackError as e: pass else: self.requests.append({ 'ip-src': ip.src, 'ip-dst': ip.dst, 'port-src': tcp.sport, 'port-dst': tcp.dport, 'tcp-data': buf_req, 'tcp-object': http_req }) self.addLogWarning( txt="<< %s http request(s) extracted" % len(self.requests)) buf_req = '' # decode http responses i = 1 self.progressBar.setValue(0) for ts, buf in pcap: self.progressBar.setValue(i) i += 1 # read ethernet layer eth = dpkt.ethernet.Ethernet(buf) if eth.type == dpkt.ethernet.ETH_TYPE_IP: # continue with ip decoding layer ip = eth.data if ip.src == ip_expected: ip_layer = (ip.src, ip.dst) if ip.p == dpkt.ip.IP_PROTO_TCP: tcp = ip.data if tcp.sport == int(port_expected) and len( tcp.data) > 0: tcp_layer = (tcp.sport, tcp.dport) if (tcp.data).startswith('HTTP/'): try: new_res = "%s\r\n\r\n" % ( tcp.data).splitlines()[0] http_res = dpkt.http.Response(new_res) except dpkt.dpkt.NeedData as e: pass except dpkt.UnpackError as e: pass else: self.responses.append({ 'ip-src': ip.src, 'ip-dst': ip.dst, 'port-src': tcp.sport, 'port-dst': tcp.dport, 'tcp-data': new_res, 'tcp-object': http_res }) self.addLogWarning( txt= "<< %s http response(s) extracted" % len(self.responses)) if self.requests: self.addLogSuccess("<< File decoded with success!") self.addLogWarning( "<< Click on the export button to generate the test!") self.exportToAction.setEnabled(True) else: self.addLogWarning("<< No http extracted!")
class TermWidget(QWidget): """Widget wich represents terminal. It only displays text and allows to enter text. All highlevel logic should be implemented by client classes """ def __init__(self, font, *args): QWidget.__init__(self, *args) self._browser = QTextEdit(self) self._browser.setReadOnly(True) document = self._browser.document() document.setDefaultStyleSheet(document.defaultStyleSheet() + "span {white-space:pre;}") self._browser.setFont(font) self._edit = _TextEdit(self, font) lowLevelWidget = self._edit.focusProxy() if lowLevelWidget is None: lowLevelWidget = self._edit lowLevelWidget.installEventFilter(self) self._edit.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum) self.setFocusProxy(self._edit) layout = QVBoxLayout(self) layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self._browser) layout.addWidget(self._edit) self._history = [''] # current empty line self._historyIndex = 0 self._edit.setFocus() def eventFilter(self, obj, event): pass # suppress docsting for non-public method """QWidget.eventFilter implementation. Catches _edit key pressings. Processes some of them """ if event.type() == QEvent.KeyPress: if event.matches(QKeySequence.MoveToNextLine): if self._edit.cursorPosition[0] == (len(self._edit.lines) - 1): self._onHistoryNext() return True elif event.matches(QKeySequence.MoveToPreviousLine): if self._edit.cursorPosition[0] == 0: self._onHistoryPrev() return True elif event.matches(QKeySequence.MoveToNextPage) or \ event.matches(QKeySequence.MoveToPreviousPage): self._browser.keyPressEvent(event) return True elif event.matches(QKeySequence.InsertParagraphSeparator): return self._editNewLineEvent() return QWidget.eventFilter(self, obj, event) def _appendToBrowser(self, style, text): """Convert text to HTML for inserting it to browser. Insert the HTML """ text = cgi.escape(text) text = text.replace('\n', '<br/>') defBg = self._browser.palette().color(QPalette.Base) h, s, v, a = defBg.getHsvF() if style == 'out': pass elif style == 'in': if v > 0.5: # white background v = v - (v / 8) # make darker else: v = v + ((1 - v) / 4) # make ligher elif style == 'err': if v < 0.5: # dark background v = v + ((1 - v) / 4) # make ligher h = 0 s = .4 elif style == 'hint': if v < 0.5: # dark background v = v + ((1 - v) / 4) # make ligher h = 0.33 s = .4 else: assert 0 bg = QColor.fromHsvF(h, s, v) text = '<span style="background-color: %s;">%s</span>' % (bg.name(), text) scrollBar = self._browser.verticalScrollBar() oldValue = scrollBar.value() if False: # hlamer: It seems, it is more comfortant, if text is always scrolled scrollAtTheEnd = oldValue == scrollBar.maximum() else: scrollAtTheEnd = True self._browser.moveCursor(QTextCursor.End) self._browser.insertHtml(text) if scrollAtTheEnd: scrollBar.setValue(scrollBar.maximum()) else: scrollBar.setValue(oldValue) while self._browser.document().characterCount() > 1024 * 1024: cursor = self._browser.cursorForPosition(QPoint(0, 0)) cursor.select(cursor.LineUnderCursor) if not cursor.selectedText(): cursor.movePosition(cursor.Down, cursor.KeepAnchor) cursor.movePosition(cursor.EndOfLine, cursor.KeepAnchor) cursor.removeSelectedText() def setLanguage(self, language): """Set highlighting language for input widget """ self._edit.detectSyntax(language=language) def execCommand(self, text): """Save current command in the history. Append it to the log. Execute child's method. Clear edit line. """ self._appendToBrowser('in', text + '\n') if len(self._history) < 2 or\ self._history[-2] != text: # don't insert duplicating items self._history.insert(-1, text) self._historyIndex = len(self._history) - 1 self._history[-1] = '' self._edit.text = '' if not text.endswith('\n'): text += '\n' self.childExecCommand(text) def childExecCommand(self, text): """Reimplement in the child classes to execute enterred commands """ pass def appendOutput(self, text): """Appent text to output widget """ self._appendToBrowser('out', text) def appendError(self, text): """Appent error text to output widget. Text is drawn with red background """ self._appendToBrowser('err', text) def appendHint(self, text): """Appent error text to output widget. Text is drawn with red background """ self._appendToBrowser('hint', text) def clear(self): """Clear the widget""" self._browser.clear() def isCommandComplete(self, text): """Executed when Enter is pressed to check if widget should execute the command, or insert newline. Implement this function in the child classes. """ return True def _editNewLineEvent(self): """Handler of Enter pressing in the edit """ text = self._edit.text if self.isCommandComplete(text): self.execCommand(text) return True # processing finished else: return False # let the editor process the event def _onHistoryNext(self): """Down pressed, show next item from the history """ if (self._historyIndex + 1) < len(self._history): self._historyIndex += 1 self._edit.text = self._history[self._historyIndex] self._edit.absCursorPosition = len(self._edit.text) def _onHistoryPrev(self): """Up pressed, show previous item from the history """ if self._historyIndex > 0: if self._historyIndex == (len(self._history) - 1): self._history[-1] = self._edit.text self._historyIndex -= 1 self._edit.text = self._history[self._historyIndex] self._edit.absCursorPosition = len(self._edit.text)