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 __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 __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 update_contents(self): self.prepareGeometryChange() self.setTextWidth(-1) self.setTextWidth(self.document().idealWidth()) self.droplet.setPos(self.rect().center().x(), self.rect().height()) self.droplet.setVisible(bool(self.branches)) fm = QFontMetrics(self.document().defaultFont()) attr = self.node_inst.attr self.attr_text_w = fm.width(attr.name if attr else "") self.attr_text_h = fm.lineSpacing() self.line_descent = fm.descent() if self.pie is not None: self.pie.setPos(self.rect().right(), self.rect().center().y())
def defaultTextGeometry(self, point): """ Return the default text geometry. Used in case the user single clicked in the scene. """ font = self.annotation_item.font() metrics = QFontMetrics(font) spacing = metrics.lineSpacing() margin = self.annotation_item.document().documentMargin() rect = QRectF(QPointF(point.x(), point.y() - spacing - margin), QSizeF(150, spacing + 2 * margin)) return rect
def defaultTextGeometry(self, point): """ Return the default text geometry. Used in case the user single clicked in the scene. """ font = self.annotation_item.font() metrics = QFontMetrics(font) spacing = metrics.lineSpacing() margin = self.annotation_item.document().documentMargin() rect = QRectF(QPointF(point.x(), point.y() - spacing - margin), QSizeF(150, spacing + 2 * margin)) return rect
def __init__(self, model, node_inst, parent=None): super().__init__(parent) self.model = model self.node_inst = node_inst fm = QFontMetrics(self.document().defaultFont()) attr = node_inst.attr self.attr_text_w = fm.width(attr.name if attr else "") self.attr_text_h = fm.lineSpacing() self.line_descent = fm.descent() self._rect = None if model.domain.class_var.is_discrete: self.pie = PieChart(node_inst.value, 8, self) else: self.pie = None
def mousePressEvent(self, event): if self.foldArea > 0: xofs = self.width() - self.foldArea font_metrics = QFontMetrics(self.edit.document().defaultFont()) fh = font_metrics.lineSpacing() ys = event.posF().y() lineNumber = 0 if event.pos().x() > xofs: pattern = self.pat if self.edit.lang != "python": pattern = self.patNotPython block = self.edit.firstVisibleBlock() viewport_offset = self.edit.contentOffset() page_bottom = self.edit.viewport().height() while block.isValid(): position = self.edit.blockBoundingGeometry( block).topLeft() + viewport_offset if position.y() > page_bottom: break if position.y() < ys and (position.y() + fh) > ys and \ pattern.match(str(block.text())): if not block.blockNumber() in self._endDocstringBlocks: lineNumber = block.blockNumber() + 1 break if position.y() < ys and (position.y() + fh) > ys and \ event.button() == Qt.LeftButton: line = block.blockNumber() if line in self._breakpoints: self._breakpoints.remove(line) else: self._breakpoints.append(line) self.update() break elif position.y() < ys and (position.y() + fh) > ys and \ event.button() == Qt.RightButton: line = block.blockNumber() if line in self._bookmarks: self._bookmarks.remove(line) else: self._bookmarks.append(line) self.update() break block = block.next() self._save_breakpoints_bookmarks() if lineNumber > 0: self.code_folding_event(lineNumber)
def mousePressEvent(self, event): if self.foldArea > 0: xofs = self.width() - self.foldArea font_metrics = QFontMetrics(self.edit.document().defaultFont()) fh = font_metrics.lineSpacing() ys = event.posF().y() lineNumber = 0 if event.pos().x() > xofs: pattern = self.pat if self.edit.lang != "python": pattern = self.patNotPython block = self.edit.firstVisibleBlock() viewport_offset = self.edit.contentOffset() page_bottom = self.edit.viewport().height() while block.isValid(): position = self.edit.blockBoundingGeometry( block).topLeft() + viewport_offset if position.y() > page_bottom: break if position.y() < ys and (position.y() + fh) > ys and \ pattern.match(str(block.text())): lineNumber = block.blockNumber() + 1 break elif position.y() < ys and (position.y() + fh) > ys and \ event.button() == Qt.LeftButton: line = block.blockNumber() if line in self._breakpoints: self._breakpoints.remove(line) else: self._breakpoints.append(line) self.update() break elif position.y() < ys and (position.y() + fh) > ys and \ event.button() == Qt.RightButton: line = block.blockNumber() if line in self._bookmarks: self._bookmarks.remove(line) else: self._bookmarks.append(line) self.update() break block = block.next() self._save_breakpoints_bookmarks() if lineNumber > 0: self.code_folding_event(lineNumber)
def sizeHint(self, which, constraint=QSizeF()): fm = QFontMetrics(self.font()) spacing = fm.lineSpacing() mleft, mtop, mright, mbottom = self.getContentsMargins() if self._root and which == Qt.PreferredSize: nleaves = len([node for node in self._items.keys() if not node.branches]) if self.orientation in [self.Left, self.Right]: return QSizeF(250, spacing * nleaves + mleft + mright) else: return QSizeF(spacing * nleaves + mtop + mbottom, 250) elif which == Qt.MinimumSize: return QSizeF(mleft + mright + 10, mtop + mbottom + 10) else: return QSizeF()
def sizeHint(self, which, constraint=QSizeF()): fm = QFontMetrics(self.font()) spacing = fm.lineSpacing() mleft, mtop, mright, mbottom = self.getContentsMargins() if self._root and which == Qt.PreferredSize: nleaves = len( [node for node in self._items.keys() if not node.branches]) if self.orientation in [self.Left, self.Right]: return QSizeF(250, spacing * nleaves + mleft + mright) else: return QSizeF(spacing * nleaves + mtop + mbottom, 250) elif which == Qt.MinimumSize: return QSizeF(mleft + mright + 10, mtop + mbottom + 10) else: return QSizeF()
def setText(self, msg): """set the text of self""" self.msg = '%s ' % msg metrics = QFontMetrics(self.font) self.width = metrics.width(self.msg) self.height = metrics.lineSpacing() * 1.1 self.setRect(0, 0, self.width, self.height) self.resetTransform() rotation = self.side.rotation() rotateCenter(self, -rotation) if rotation % 180 == 0: yOffset = self.rect().height() if rotation == 0: yOffset = 2 * -yOffset if rotation == 180: self.translate(self.rect().width()/2, yOffset) else: self.translate(-self.rect().width()/2, yOffset) else: self.translate(-self.rect().width()/2, -self.rect().height()/2)
def setText(self, msg): """set the text of self""" self.msg = '%s ' % msg metrics = QFontMetrics(self.font) self.width = metrics.width(self.msg) self.height = metrics.lineSpacing() * 1.1 self.setRect(0, 0, self.width, self.height) self.resetTransform() rotation = self.side.rotation() rotateCenter(self, -rotation) if rotation % 180 == 0: yOffset = self.rect().height() if rotation == 0: yOffset = 2 * -yOffset if rotation == 180: self.translate(self.rect().width()/2, yOffset) else: self.translate(-self.rect().width()/2, yOffset) else: self.translate(-self.rect().width()/2, -self.rect().height()/2)
class KhtTextEdit(QPlainTextEdit): """ Widget which handle all specifities of implemented in the editor""" show_progress = pyqtSignal(bool) def __init__(self, parent=None, filename=None): """Initialization, can accept a filepath as argument""" QPlainTextEdit.__init__(self, parent) # Errors self.errors = {} self.isMAEMO = False self.scroller = None palette = self.palette() palette.setColor(QPalette.Base, Qt.white) palette.setColor(QPalette.Text, Qt.black) self.setPalette(palette) self.setWindowOpacity(0.9) self.hl_color = QColor('lightblue').lighter(120) self.qt18720 = False if ((parent.settings.value("qt18720")) == '2'): self.qt18720 = True else: self.qt18720 = False # Brace matching self.bracepos = None # Init scroller and area which are tricky hack to speed scrolling # try: # scroller = self.property("kineticScroller") # scroller.setEnabled(True) # except: # print 'Cannot instance kineticScroller' #Plugin init moved to editor_window.py #initialization init of plugin system #Maybe be not the best place to do it ... #init_plugin_system({'plugin_path': '/home/opt/khteditor/plugins', # 'plugins': ['autoindent']}) #If we have a filename self.filename = filename if (self.filename == None) or (self.filename == ''): self.filename = u'Unnamed.txt' self.document().setModified(False) parent.setWindowTitle(self.filename) #Set no wrap if (bool(parent.settings.value("WrapLine"))): self.setLineWrapMode(QPlainTextEdit.NoWrap) else: self.setLineWrapMode(QPlainTextEdit.WidgetWidth) font = QFont() try: if parent.settings.contains('FontName'): font.setFamily(parent.settings.value('FontName')) else: font.setFamily("Courier") except: font.setFamily("Courier") #Get Font Size try: if parent.settings.contains('FontSize'): font.setPointSize(int(parent.settings.value('FontSize'))) else: font.setPointSize(11) except: font.setPointSize(11) #Set Font self.fmetrics = QFontMetrics(font) self.document().setDefaultFont(font) #Remove auto capitalization self.setInputMethodHints(Qt.ImhNoAutoUppercase) #Keep threaded plugins references to avoid them to be garbage collected self.threaded_plugins = [] self.enabled_plugins = parent.enabled_plugins #Current Line highlight and Bracket matcher self.cursorPositionChanged.connect(self.curPositionChanged) self.textChanged.connect(self.textEditChanged) # Brackets ExtraSelection ... def detectLanguage(self, filename): for extension, lang in LANGUAGES: if filename.endswith(extension.lower()): return lang return None def loadHighlighter(self, filename=None): filename = self.filename language = self.detectLanguage(filename) #Return None if language not yet implemented natively in KhtEditor if language == 'python': self.show_progress.emit(True) QApplication.processEvents() from syntax.python_highlighter import Highlighter self.highlighter = Highlighter(self.document()) QApplication.processEvents() self.show_progress.emit(False) elif (language != None) and (language != 'None'): self.show_progress.emit(True) QApplication.processEvents() from syntax.generic_highlighter import Highlighter self.highlighter = Highlighter(self.document(), language) QApplication.processEvents() self.show_progress.emit(False) else: self.show_progress.emit(True) QApplication.processEvents() from syntax import pygments_highlighter self.highlighter = \ pygments_highlighter.Highlighter(self.document(), unicode(filename)) QApplication.processEvents() self.show_progress.emit(False) def textEditChanged(self): if self.scroller: #Resize doc = self.document() s = doc.size().toSize() s.setHeight((s.height() + 1) * (self.fmetrics.lineSpacing() + 1)) fr = self.frameRect() cr = self.contentsRect() self.setMinimumHeight( max(70, s.height() + (fr.height() - cr.height() - 1))) self.setMinimumWidth( max(240, s.width() + (fr.width() - cr.width()) - 1)) # Remove ensureVisible Hack which is now fixed in qt 4.7.2 # def ensureVisible(self,pos,xmargin,ymargin): # # visible = self.area.viewport().size() # currentPos = QPoint(self.area.horizontalScrollBar().value(), # self.area.verticalScrollBar().value()) # posRect = QRect(pos.x()-xmargin, pos.y()-ymargin,2*xmargin,2*ymargin) # visibleRect = QRect(currentPos, visible) # # if (visibleRect.contains(posRect)): # return # # newPos = currentPos # if (posRect.top() < visibleRect.top()): # newPos.setY(posRect.top()) # elif (posRect.bottom() > visibleRect.bottom()): # newPos.setY(posRect.bottom() - visible.height()) # if (posRect.left() < visibleRect.left()): # newPos.setX(posRect.left()) # elif (posRect.right() > visibleRect.right()): # newPos.setX(posRect.right() - visible.width()) # self.scroller.scrollTo(newPos) def curPositionChanged(self): #Plugin hook for plugin in filter_plugins_by_capability( 'beforeCursorPositionChanged', self.enabled_plugins): plugin.do_beforeCursorPositionChanged(self) #Hilight current line #Workarround QTBUG-18720 self.highlightCurrentLine() #Make sure cursor is visible #self.ensureCursorVisible() cursor = self.cursorRect() pos = cursor.center() #self.ensureVisible(pos.x(),pos.y(), 2*cursor.width()+20, 2*cursor.height()) if self.scroller: self.scroller.ensureVisible(pos.x(), pos.y(), 2 * cursor.width() + 20, 2 * cursor.height()) def match_left(self, block, character, start, found): map = {'{': '}', '(': ')', '[': ']'} block_jump = 0 while block.isValid() and (block_jump < 20): data = block.userData() if data is not None: braces = data.braces N = len(braces) for k in range(start, N): if braces[k].character == character: found += 1 if braces[k].character == map[character]: if not found: return braces[k].position + block.position() else: found -= 1 block = block.next() block_jump += 1 start = 0 def match_right(self, block, character, start, found): map = {'}': '{', ')': '(', ']': '['} block_jump = 0 while block.isValid() and (block_jump < 20): data = block.userData() if data is not None: braces = data.braces if start is None: start = len(braces) for k in range(start - 1, -1, -1): if braces[k].character == character: found += 1 if braces[k].character == map[character]: if found == 0: return braces[k].position + block.position() else: found -= 1 block = block.previous() block_jump += 1 start = None def check_brackets(self): left, right = QTextEdit.ExtraSelection(),\ QTextEdit.ExtraSelection() cursor = self.textCursor() block = cursor.block() data = block.userData() previous, next = None, None if data is not None: position = cursor.position() block_position = cursor.block().position() braces = data.braces N = len(braces) for k in range(0, N): if braces[k].position == position - block_position or\ braces[k].position == position - block_position - 1: previous = braces[k].position + block_position if braces[k].character in ['{', '(', '[']: next = self.match_left(block, braces[k].character, k + 1, 0) elif braces[k].character in ['}', ')', ']']: next = self.match_right(block, braces[k].character, k, 0) # if next is None: # next = -1 if (next is not None and next > 0) \ and (previous is not None and previous > 0): format = QTextCharFormat() cursor.setPosition(previous) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('blue')) left.format = format left.cursor = cursor cursor.setPosition(next) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('blue')) right.format = format right.cursor = cursor return left, right elif previous is not None: format = QTextCharFormat() cursor.setPosition(previous) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('red')) left.format = format left.cursor = cursor return (left, ) elif next is not None: format = QTextCharFormat() cursor.setPosition(next) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('red')) left.format = format left.cursor = cursor return (left, ) #PySide Bug : The type of e is QEvent instead of QKeyEvent def keyPressEvent(self, event): """Intercept the key event to lets plugin do something if they want""" if event.type() == QEvent.KeyPress: for plugin in filter_plugins_by_capability('beforeKeyPressEvent', self.enabled_plugins): plugin.do_beforeKeyPressEvent(self, event) QPlainTextEdit.keyPressEvent(self, event) for plugin in filter_plugins_by_capability('afterKeyPressEvent', self.enabled_plugins): plugin.do_afterKeyPressEvent(self, event) def closeEvent(self, event): """Catch the close event and ask to save if document is modified""" answer = self.document().isModified() and \ QMessageBox.question(self, "Text Editor - Unsaved Changes", "Save unsaved changes in %s?" % self.filename, QMessageBox.Yes| QMessageBox.No| QMessageBox.Close) if answer == QMessageBox.Yes: try: self.save() event.accept() except (IOError, OSError), ioError: QMessageBox.warning( self, "Text Editor -- Save Error", "Failed to save %s: %s" % (self.filename, ioError)) event.ignore() elif answer == QMessageBox.Close: return event.ignore()
class PortraitSpecificDelegate(QObject): def __init__(self, viewDelegate): QObject.__init__(self) self.viewDelegate = viewDelegate self.nameFont = self.viewDelegate.configureTextFont(16, QFont.Normal) self.tickerFont = self.viewDelegate.configureTextFont(14, QFont.Normal) self.currentPriceFont = self.viewDelegate.configureTextFont(32, QFont.Bold) self.changeFont = self.viewDelegate.configureTextFont(24, QFont.Normal) self.rightColFont = self.viewDelegate.configureTextFont(14, QFont.Normal) self.fontMetricsRightCol = QFontMetrics(self.rightColFont) self.lineSpRightCol = self.fontMetricsRightCol.lineSpacing() def getNameFont(self): return self.nameFont def getTickerFont(self): return self.tickerFont def getCurrentPriceFont(self): return self.currentPriceFont def getChangeFont(self): return self.changeFont def sizeHint(self, option, index): ''' Portrait mode - Left column Name (Symbol) -------------- Current Price Change ''' textHeightLCol = self.viewDelegate.MARGIN + \ QFontMetrics(self.nameFont).lineSpacing() + \ self.viewDelegate.MARGIN + \ QFontMetrics(self.currentPriceFont).lineSpacing() + \ self.viewDelegate.MARGIN + \ QFontMetrics(self.changeFont).lineSpacing() + \ self.viewDelegate.MARGIN ''' Portrait mode - Right column Name (Symbol) -------------- PE ratio Market Cap Daily volume Average volume Delay ''' textHeightRCol = self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.nameFont).lineSpacing() + \ self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.rightColFont).lineSpacing() + \ self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.rightColFont).lineSpacing() + \ self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.rightColFont).lineSpacing() + \ self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.rightColFont).lineSpacing() + \ self.viewDelegate.MARGIN_RCOL + \ QFontMetrics(self.rightColFont).lineSpacing() + \ self.viewDelegate.MARGIN hint = QSize(0, max(textHeightLCol, textHeightRCol)) return hint def paintRightCol(self, index, painter, rightColRect): ''' @param QModelIndex index @param QPainter painter @param QRect rightColRect ''' painter.setFont(self.rightColFont) painter.setPen(QPen(Qt.gray)) m = index.model() lineSp = self.lineSpRightCol + self.viewDelegate.MARGIN_RCOL # PE ratio pe = m.data(index, PositionsModel.ROLE_PE) peStr = self.tr("PE ratio: ") + pe painter.drawText(rightColRect, Qt.AlignTop | Qt.AlignRight, peStr) # Market cap mktCap = m.data(index, PositionsModel.ROLE_MKT_CAP) mktCapStr = self.tr("Mkt Cap: ") + mktCap rightColRect.adjust(0, lineSp, 0, lineSp) painter.drawText(rightColRect, Qt.AlignTop | Qt.AlignRight, mktCapStr) # Daily Volume vol = m.data(index, PositionsModel.ROLE_DAILY_VOL) volStr = self.tr("Vol: ") + QString(vol) rightColRect.adjust(0, lineSp, 0, lineSp) painter.drawText(rightColRect, Qt.AlignTop | Qt.AlignRight, volStr) # Average Volume avgVol = m.data(index, PositionsModel.ROLE_AVG_VOL) avgVolStr = self.tr("Avg Vol: ") + QString(avgVol) rightColRect.adjust(0, lineSp, 0, lineSp) painter.drawText(rightColRect, Qt.AlignTop | Qt.AlignRight, avgVolStr) # Delay delay = m.data(index, PositionsModel.ROLE_DELAY) if delay == "": delayStr = self.tr("Realtime data") else: delayStr = self.tr("Delay: ") + delay + self.tr(" mins") rightColRect.adjust(0, lineSp, 0, lineSp) painter.drawText(rightColRect, Qt.AlignTop | Qt.AlignRight, delayStr)
class KhtTextEdit(QPlainTextEdit): """ Widget which handle all specifities of implemented in the editor""" show_progress = pyqtSignal(bool) def __init__(self, parent=None, filename=None): """Initialization, can accept a filepath as argument""" QPlainTextEdit.__init__(self, parent) # Errors self.errors = {} self.isMAEMO = False self.scroller = None palette = self.palette(); palette.setColor(QPalette.Base, Qt.white) palette.setColor(QPalette.Text, Qt.black) self.setPalette(palette) self.setWindowOpacity(0.9) self.hl_color = QColor('lightblue').lighter(120) self.qt18720 = False if ((parent.settings.value("qt18720"))=='2'): self.qt18720 = True else: self.qt18720 = False # Brace matching self.bracepos = None # Init scroller and area which are tricky hack to speed scrolling # try: # scroller = self.property("kineticScroller") # scroller.setEnabled(True) # except: # print 'Cannot instance kineticScroller' #Plugin init moved to editor_window.py #initialization init of plugin system #Maybe be not the best place to do it ... #init_plugin_system({'plugin_path': '/home/opt/khteditor/plugins', # 'plugins': ['autoindent']}) #If we have a filename self.filename = filename if (self.filename == None) or (self.filename == ''): self.filename = u'Unnamed.txt' self.document().setModified(False) parent.setWindowTitle(self.filename) #Set no wrap if (bool(parent.settings.value("WrapLine"))): self.setLineWrapMode( QPlainTextEdit.NoWrap) else: self.setLineWrapMode( QPlainTextEdit.WidgetWidth) font = QFont() try: if parent.settings.contains('FontName'): font.setFamily(parent.settings.value('FontName')) else: font.setFamily("Courier") except: font.setFamily("Courier") #Get Font Size try: if parent.settings.contains('FontSize'): font.setPointSize(int(parent.settings.value('FontSize'))) else: font.setPointSize(11) except: font.setPointSize(11) #Set Font self.fmetrics = QFontMetrics(font) self.document().setDefaultFont(font) #Remove auto capitalization self.setInputMethodHints(Qt.ImhNoAutoUppercase) #Keep threaded plugins references to avoid them to be garbage collected self.threaded_plugins = [] self.enabled_plugins = parent.enabled_plugins #Current Line highlight and Bracket matcher self.cursorPositionChanged.connect(self.curPositionChanged) self.textChanged.connect(self.textEditChanged) # Brackets ExtraSelection ... def detectLanguage(self,filename): for extension,lang in LANGUAGES: if filename.endswith(extension.lower()): return lang return None def loadHighlighter(self,filename=None): filename = self.filename language = self.detectLanguage(filename) #Return None if language not yet implemented natively in KhtEditor if language == 'python': self.show_progress.emit(True) QApplication.processEvents() from syntax.python_highlighter import Highlighter self.highlighter = Highlighter(self.document()) QApplication.processEvents() self.show_progress.emit(False) elif (language != None) and (language != 'None'): self.show_progress.emit(True) QApplication.processEvents() from syntax.generic_highlighter import Highlighter self.highlighter = Highlighter(self.document(),language) QApplication.processEvents() self.show_progress.emit(False) else: self.show_progress.emit(True) QApplication.processEvents() from syntax import pygments_highlighter self.highlighter = \ pygments_highlighter.Highlighter(self.document(), unicode(filename)) QApplication.processEvents() self.show_progress.emit(False) def textEditChanged(self): if self.scroller: #Resize doc = self.document() s = doc.size().toSize() s.setHeight((s.height() + 1) * (self.fmetrics.lineSpacing()+1) ) fr = self.frameRect() cr = self.contentsRect() self.setMinimumHeight(max(70, s.height() + (fr.height() - cr.height() - 1))) self.setMinimumWidth(max(240,s.width() + (fr.width()-cr.width()) - 1)) # Remove ensureVisible Hack which is now fixed in qt 4.7.2 # def ensureVisible(self,pos,xmargin,ymargin): # # visible = self.area.viewport().size() # currentPos = QPoint(self.area.horizontalScrollBar().value(), # self.area.verticalScrollBar().value()) # posRect = QRect(pos.x()-xmargin, pos.y()-ymargin,2*xmargin,2*ymargin) # visibleRect = QRect(currentPos, visible) # # if (visibleRect.contains(posRect)): # return # # newPos = currentPos # if (posRect.top() < visibleRect.top()): # newPos.setY(posRect.top()) # elif (posRect.bottom() > visibleRect.bottom()): # newPos.setY(posRect.bottom() - visible.height()) # if (posRect.left() < visibleRect.left()): # newPos.setX(posRect.left()) # elif (posRect.right() > visibleRect.right()): # newPos.setX(posRect.right() - visible.width()) # self.scroller.scrollTo(newPos) def curPositionChanged(self): #Plugin hook for plugin in filter_plugins_by_capability('beforeCursorPositionChanged',self.enabled_plugins): plugin.do_beforeCursorPositionChanged(self) #Hilight current line #Workarround QTBUG-18720 self.highlightCurrentLine() #Make sure cursor is visible #self.ensureCursorVisible() cursor = self.cursorRect() pos = cursor.center() #self.ensureVisible(pos.x(),pos.y(), 2*cursor.width()+20, 2*cursor.height()) if self.scroller: self.scroller.ensureVisible(pos.x(),pos.y(),2*cursor.width()+20, 2*cursor.height()) def match_left(self, block, character, start, found): map = {'{': '}', '(': ')', '[': ']'} block_jump = 0 while block.isValid() and (block_jump < 20): data = block.userData() if data is not None: braces = data.braces N = len(braces) for k in range(start, N): if braces[k].character == character: found += 1 if braces[k].character == map[character]: if not found: return braces[k].position + block.position() else: found -= 1 block = block.next() block_jump += 1 start = 0 def match_right(self, block, character, start, found): map = {'}': '{', ')': '(', ']': '['} block_jump = 0 while block.isValid() and (block_jump < 20): data = block.userData() if data is not None: braces = data.braces if start is None: start = len(braces) for k in range(start - 1, -1, -1): if braces[k].character == character: found += 1 if braces[k].character == map[character]: if found == 0: return braces[k].position + block.position() else: found -= 1 block = block.previous() block_jump += 1 start = None def check_brackets(self): left, right = QTextEdit.ExtraSelection(),\ QTextEdit.ExtraSelection() cursor = self.textCursor() block = cursor.block() data = block.userData() previous, next = None, None if data is not None: position = cursor.position() block_position = cursor.block().position() braces = data.braces N = len(braces) for k in range(0, N): if braces[k].position == position - block_position or\ braces[k].position == position - block_position - 1: previous = braces[k].position + block_position if braces[k].character in ['{', '(', '[']: next = self.match_left(block, braces[k].character, k + 1, 0) elif braces[k].character in ['}', ')', ']']: next = self.match_right(block, braces[k].character, k, 0) # if next is None: # next = -1 if (next is not None and next > 0) \ and (previous is not None and previous > 0): format = QTextCharFormat() cursor.setPosition(previous) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('blue')) left.format = format left.cursor = cursor cursor.setPosition(next) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('blue')) right.format = format right.cursor = cursor return left, right elif previous is not None: format = QTextCharFormat() cursor.setPosition(previous) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('red')) left.format = format left.cursor = cursor return (left,) elif next is not None: format = QTextCharFormat() cursor.setPosition(next) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor) format.setForeground(QColor('white')) format.setBackground(QColor('red')) left.format = format left.cursor = cursor return (left,) #PySide Bug : The type of e is QEvent instead of QKeyEvent def keyPressEvent(self, event): """Intercept the key event to lets plugin do something if they want""" if event.type() == QEvent.KeyPress: for plugin in filter_plugins_by_capability('beforeKeyPressEvent',self.enabled_plugins): plugin.do_beforeKeyPressEvent(self,event) QPlainTextEdit.keyPressEvent(self, event) for plugin in filter_plugins_by_capability('afterKeyPressEvent',self.enabled_plugins): plugin.do_afterKeyPressEvent(self,event) def closeEvent(self,event): """Catch the close event and ask to save if document is modified""" answer = self.document().isModified() and \ QMessageBox.question(self, "Text Editor - Unsaved Changes", "Save unsaved changes in %s?" % self.filename, QMessageBox.Yes| QMessageBox.No| QMessageBox.Close) if answer == QMessageBox.Yes: try: self.save() event.accept() except (IOError, OSError), ioError: QMessageBox.warning(self, "Text Editor -- Save Error", "Failed to save %s: %s" % (self.filename, ioError)) event.ignore() elif answer == QMessageBox.Close: return event.ignore()
def paint (self, painter, option, index): ''' QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ''' orntnDelegate = self.chooseOrientationDelegate() painter.save() if option.state & QStyle.State_Selected: borderPen = QPen(Qt.blue) borderPen.setWidth(3) nameBgColors = [Qt.white, Qt.yellow] else: borderPen = QPen(Qt.lightGray) lightBlue = QColor(0, 0, 255).lighter(180) nameBgColors = [Qt.white, lightBlue] # Set default font and color itemRect = option.rect painter.fillRect(itemRect, Qt.white) painter.setFont(orntnDelegate.getNameFont()) painter.setPen(Qt.black) m = index.model() ticker = m.data(index, PositionsModel.ROLE_TICKER) companyName = m.data(index, Qt.DisplayRole) line2 = m.data(index, PositionsModel.ROLE_CURRENT_PRICE) line3 = m.data(index, PositionsModel.ROLE_CHANGE) fontMetricsCompanyName = QFontMetrics(orntnDelegate.getNameFont()) fontMetricsTicker = QFontMetrics(orntnDelegate.getTickerFont()) fontMetricsCurrentPrice = QFontMetrics(orntnDelegate.getCurrentPriceFont()) fontMetricsChange = QFontMetrics(orntnDelegate.getChangeFont()) lineSp1 = fontMetricsCompanyName.lineSpacing() lineSp2 = fontMetricsCurrentPrice.lineSpacing() lineSp3 = fontMetricsChange.lineSpacing() # Company Name (EXCHANGE:SYMBOL) textRectShade = QRect(itemRect.left(), itemRect.top(), itemRect.width(), self.MARGIN + lineSp1 + self.MARGIN) gradient = self.createLinearGradient(textRectShade, nameBgColors[0], nameBgColors[1]) painter.fillRect(textRectShade, gradient) textRect = QRect(itemRect.left() + self.MARGIN, itemRect.top() + self.MARGIN, itemRect.width() - 2 * self.MARGIN, lineSp1 + self.MARGIN) painter.setFont(orntnDelegate.getNameFont()) # Shorten the company name such that long company names are not written on top of the ticker tickerTextW = fontMetricsTicker.width(ticker) companyNameTextW = textRect.width() - tickerTextW - 2 * self.MARGIN companyName = fontMetricsCompanyName.elidedText(companyName, Qt.ElideRight, companyNameTextW) painter.drawText(textRect, Qt.AlignVCenter | Qt.AlignLeft, companyName) painter.setFont(orntnDelegate.getTickerFont()) painter.drawText(textRect, Qt.AlignVCenter | Qt.AlignRight, "(%s)" % (ticker)) # Current price painter.setFont(orntnDelegate.getCurrentPriceFont()) textRect.adjust(0, lineSp1 + self.MARGIN, 0, lineSp2 + self.MARGIN) painter.drawText(textRect, Qt.AlignTop | Qt.AlignLeft, line2) rightColRect = QRect(textRect.left(), textRect.top(), textRect.width(), textRect.height()) # Change ccol = m.data(index, PositionsModel.ROLE_CHANGE_COLOR) if ccol == "chg": painter.setPen(QPen(Qt.darkGreen)) elif ccol == "chr": painter.setPen(QPen(Qt.red)) painter.setFont(orntnDelegate.getChangeFont()) textRect.adjust(0, lineSp2 + self.MARGIN, 0, lineSp3 + self.MARGIN) painter.drawText(textRect, Qt.AlignTop | Qt.AlignLeft, line3) ''' Right Column ''' orntnDelegate.paintRightCol(index, painter, rightColRect) painter.setPen(borderPen) painter.drawRect(itemRect) painter.restore()