from PyQt4.QtGui import QPlainTextEdit, QWidget, QVBoxLayout, QApplication, \

QFileDialog, QMessageBox, QTextBrowser, QDockWidget, \

QMainWindow, QIcon, QHBoxLayout, QPainter, QGraphicsWidget, \

QFontMetrics, QFrame, QTextEdit, QTextFormat, \

QTextBlockUserData, QColor, QFont, QTextCursor, \

QSyntaxHighlighter, QTextCharFormat

from PyQt4.QtCore import QString, SIGNAL as SIG, Qt, QEvent, QVariant,\

QRect, QRegExp, QThread

import sys, os, re

from subprocess import Popen, PIPE

NUMBER_BAR_COLOR = QColor(180, 215, 140)

BRACKET_MATCHED = QColor('blue')

BRACKET_UNMATCHED = QColor('red')

CURRENT_LINE_HL  = QColor(200, 205, 0, 70)

class BracketsInfo:

def __init__(self, character, position):

self.character = character

self.position  = position

class TextBlockData(QTextBlockUserData):

def __init__(self, parent = None):

super(TextBlockData, self).__init__()

self.braces = []

self.valid = False

def insert_brackets_info(self, info):

self.valid = True

self.braces.append(info)

def isValid(self):

return self.valid

class LaTeX(QSyntaxHighlighter):

command = QRegExp(r'\\(\w+)?')

cmd_fmt = QTextCharFormat()

cmd_fmt.setForeground(QColor('darkRed'))

comment = QRegExp(r'%(.*)?')

cmnt_fmt = QTextCharFormat()

cmnt_fmt.setForeground(QColor('gray'))

keywords = QRegExp(r'\\begin|\\end|\\label|\\ref|\\(sub)?(sub)?section')

keyword_fmt = QTextCharFormat()

keyword_fmt.setForeground(QColor('red'))

rules = [(command, cmd_fmt),

(comment, cmnt_fmt),

(keywords, keyword_fmt)]

def __init__(self, parent):

super(LaTeX, self).__init__(parent)

def highlightBlock(self, text):

braces = QRegExp('(\{|\}|\(|\)|\[|\])')

math_delimiters = QRegExp(r'(\\begin{equation\*?}|' +\

r'\\begin{align\*?}|' +\

r'\\begin{displaymath\*?})')

begin_end = QRegExp(r'(\\begin{|\\end{|\\ref|\\label)')

block_data = TextBlockData()

index = braces.indexIn(text)

while index >= 0:

matched_brace = str(braces.capturedTexts()[0])

info = BracketsInfo(matched_brace, index)

block_data.insert_brackets_info(info)

index = braces.indexIn(text, index + 1)

self.setCurrentBlockUserData(block_data)

for regex, fmt in LaTeX.rules:

start = regex.indexIn(text, 0)

while start >= 0:

length = regex.matchedLength()

self.setFormat(start, length, fmt)

start = regex.indexIn(text, start + length)

self.setCurrentBlockState(0)

class NumberBar(QWidget):

def __init__(self, parent = None):

super(NumberBar, self).__init__(parent)

self.edit = parent

layout = QVBoxLayout()

self.setLayout(layout)

self.edit.blockCountChanged.connect(self.update_width)

self.edit.updateRequest.connect(self.update_on_scroll)

self.update_width('1')

def update_on_scroll(self, rect, scroll):

if self.isVisible():

if scroll:

self.scroll(0, scroll)

else:

self.update()

def update_width(self, string):

width = self.fontMetrics().width(unicode(string)) + 20

if self.width() != width:

self.setFixedWidth(width)

def paintEvent(self, event):

if self.isVisible():

block = self.edit.firstVisibleBlock()

height = self.fontMetrics().height()

number = block.blockNumber()

painter = QPainter(self)

painter.fillRect(event.rect(), NUMBER_BAR_COLOR)

font = painter.font()

current_block = self.edit.textCursor().block().blockNumber() + 1

condition = True

while block.isValid() and condition:

block_geometry = self.edit.blockBoundingGeometry(block)

offset = self.edit.contentOffset()

block_top = block_geometry.translated(offset).top()

number += 1

rect = QRect(0, block_top, self.width() - 5, height)

if number == current_block:

font.setBold(True)

else:

font.setBold(False)

painter.setFont(font)

painter.drawText(rect, Qt.AlignRight, '%i'%number)

if block_top > event.rect().bottom():

condition = False

block = block.next()

painter.end()

class QLaTeXEdit(QWidget):

def __init__(self, parent = None):

super(QLaTeXEdit, self).__init__(parent)

# Editor Widget ...

self.edit = QPlainTextEdit()

self.edit.setFrameStyle(QFrame.NoFrame)

self.extra_selections = []

# Line Numbers ...

self.numbers = NumberBar(self.edit)

# Syntax Highlighter ...

self.highlighter = LaTeX(self.edit.document())

# Laying out...

layout = QHBoxLayout()

layout.setSpacing(1.5)

layout.addWidget(self.numbers)

layout.addWidget(self.edit)

self.setLayout(layout)

# Event Filter ...

self.installEventFilter(self)

self.edit.cursorPositionChanged.connect(self.check_brackets)

# Brackets ExtraSelection ...

self.left_selected_bracket  = QTextEdit.ExtraSelection()

self.right_selected_bracket = QTextEdit.ExtraSelection()

def set_numbers_visible(self, value = True):

self.numbers.setVisible(False)

def match_left(self, block, character, start, found):

map = {'{': '}', '(': ')', '[': ']'}

while block.isValid():

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

start = 0

def match_right(self, block, character, start, found):

map = {'}': '{', ')': '(', ']': '['}

while block.isValid():

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

start = None

def check_brackets(self):

left, right = QTextEdit.ExtraSelection(),\

QTextEdit.ExtraSelection()

cursor = self.edit.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:

if next == 0 and next >= 0:

format = QTextCharFormat()

cursor.setPosition(previous)

cursor.movePosition(QTextCursor.NextCharacter,

QTextCursor.KeepAnchor)

format.setForeground(BRACKET_MATCHED)

format.setBackground(QColor('white'))

self.left_selected_bracket.format = format

self.left_selected_bracket.cursor = cursor

cursor.setPosition(next)

cursor.movePosition(QTextCursor.NextCharacter,

QTextCursor.KeepAnchor)

format.setForeground(BRACKET_MATCHED)

format.setBackground(QColor('white'))

self.right_selected_bracket.format = format

self.right_selected_bracket.cursor = cursor

def paintEvent(self, event):

highlighted_line = QTextEdit.ExtraSelection()

highlighted_line.format.setBackground(CURRENT_LINE_HL)

highlighted_line.format.setProperty(QTextFormat\

.FullWidthSelection,

QVariant(True))

highlighted_line.cursor = self.edit.textCursor()

highlighted_line.cursor.clearSelection()

self.edit.setExtraSelections([highlighted_line,

self.left_selected_bracket,

self.right_selected_bracket])

def document(self):

return self.edit.document

def getPlainText(self):

return unicode(self.edit.toPlainText())

def isModified(self):

return self.edit.document().isModified()

def setModified(self, modified):

self.edit.document().setModified(modified)

def setLineWrapMode(self, mode):

self.edit.setLineWrapMode(mode)

def clear(self):

self.edit.clear()

def setPlainText(self, *args, **kwargs):

self.edit.setPlainText(*args, **kwargs)

def setDocumentTitle(self, *args, **kwargs):

self.edit.setDocumentTitle(*args, **kwargs)

def eventFilter(self, object, event):

if event.type() == QEvent.KeyPress:

if event.key() == Qt.Key_Return:

QPlainTextEdit.event(self, event)

print 'return pressed'

return True

if event.key() == Qt.Key_F6:

self.emit(SIG('pdflatex'))

return True

if event.key() == Qt.Key_F7:

self.emit(SIG('pdfshow'))

return True

if event.key() == Qt.Key_S and\

event.modifiers() == Qt.ControlModifier:

self.emit(SIG('save_document'))

return True

if event.key() == Qt.Key_O and\

event.modifiers() == Qt.ControlModifier:

self.emit(SIG('open_document'))

return True

if event.key() == Qt.Key_N and\

event.modifiers() == Qt.ControlModifier:

self.emit(SIG('new_document'))

return True

if event.key() == Qt.Key_W and\

event.modifiers() == Qt.ControlModifier:

self.emit(SIG('close_document'))

return True

else:

return False

return False

def set_number_bar_visible(self, value):

self.numbers.setVisible(value)

if __name__ == '__main__':

app = QApplication(sys.argv)

win = QLaTeXEdit()

win.show()

app.exec_()

pyqt颜色字符的更多相关文章

  1. Linux Shell输出颜色字符学习笔记(附Python脚本实现自动化定制生成)

    齿轮发出咔嚓一声,向前进了一格.而一旦向前迈进,齿轮就不能倒退了.这就是世界的规则. 0x01背景 造了个轮子:御剑师傅的ipintervalmerge的Python版本.觉得打印的提示信息如果是普通 ...

  2. python - 2 8 16进制/颜色/字符编码

    1.二进制 八进制 十六进制 二进制: bin() 0b10010八进制: oct() 0o10十进制: 1-100十六进制: hex() 0X53 BH 十进制转2, 8,16进制: >> ...

  3. 显示log里的ansi codecs颜色字符

    方法: vim AnsiEsc插件 http://www.vim.org/scripts/script.php?script_id=302 less -r cat和tail命令都可以正常显示,而且ta ...

  4. [转载]Linux下终端字体颜色设置方法

    原文地址:Linux下终端字体颜色设置方法作者:router 网上类似的文章有很多,但是都是转来转去的,没有经过测试,按照很多文章的方法会造成你设置之后的终端在换行和删除输入字符时终端显示会乱七八糟, ...

  5. Markdown文字添加颜色

    转自:原文地址 添加红色 效果: 写法: $\color{red}{red}$ 添加绿色 效果: 写法: $\color{green}{green}$ 添加蓝色 效果: 写法: $\color{blu ...

  6. Linux字符界面字符颜色显示

    一.字符颜色 #!/bin/bash #字符颜色显示 #-e:允许echo使用转义 #\033[:开始位 #\033[0m:结束位 #\033等同于\e echo -e "\033[30m黑 ...

  7. 【canvas学习笔记三】样式和颜色

    上一节我们学习了如何用路径绘制各种形状,但我们只能用默认的颜色和线条.这节就来学习设置不同的颜色和线条样式. 颜色 设置颜色主要有两个属性: fillStyle = color 设置填充颜色 stro ...

  8. HTML 学习笔记 CSS样式(文本)

    CSS文本属性可以定义文本的外观 通过文本属性 您可以改变文本的颜色 字符间距 文本对齐装饰文本 对文本进行缩进等等. 缩进文本 把web页面上的段落的第一行缩进,这是最常用的文本格式化效果. css ...

  9. qt_文本编辑器实现_附带详细注释和源码下载

    源码下载: 链接: http://pan.baidu.com/s/1c21EVRy 密码: qub8 实现主要的功能有:新建,打开,保存,另存为,查找(查找的时候需要先将光标放到最下面位置才能查全,不 ...

随机推荐

  1. Sublime Text2 按shift键选择不了的问题

    记录下来,免得以后忘了: 今天在Sublime Text 2装了一个ThinkPHP插件之后.发现按shift键+鼠标左键选择不了内容了.原因是ThinkPHP里的热键与系统的有冲突了,须要设置例如以 ...

  2. LeetCode::Remove Duplicates from Sorted List II [具体分析]

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  3. android SlidingTabLayout实现ViewPager页卡滑动效果

    先来张效果图(能够滑动切换页卡) watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcGVuZ2t2/font/5a6L5L2T/fontsize/400/fi ...

  4. Java基础知识强化66:基本类型包装类之JDK5新特性自动装箱和拆箱

    1. JDK1.5以后,简化了定义方式. (1)Integer  x = new  Integer(4):可以直接写成如下:         Integer  x = 4 ://自动装箱,通过valu ...

  5. CVE-2015-8660分析

    0x00测试环境   使用环境 备注 操作系统 Ubuntu15.04 虚拟机 内核版本 3.19.0-15-generic 漏洞来源 /fs/overlayfs/inode.c Before 201 ...

  6. Word01-从正文处开始插入页码

    一份正式的文档应该由以下几部分组成:封面.目录.摘要.正文…… 现在要求前三页不需要插入页码,从正文部分插入页码为第一页,原文档如下: 步骤: 第一步:将光标移动到摘要页的末尾,选择页面部局--> ...

  7. extJs项目实战

    extjs是因为在公司用到一次,也是公司唯一一个extjs的项目,当时拿到这个需求的时候,我有点懵逼,这他妈的什么鬼,参加工作两年不到的纯小白,没办法,这是工作,必须要完成的.硬着头皮做吧,好在最后弄 ...

  8. ExtJs在vs中的应用

    目标: 认识EXTJS(自己google) 在vs中创建EXTJS的编程环境 通过一个简单的例子了解EXTJS编程过程 内容: 个人理解EXTJS是一个基于ajax富客户端应用程序框架, 1,创建vs ...

  9. OD: Register, Stack Frame, Function Reference

    几个重要的 Win32 寄存器 EIP 指令寄存器(Extended Instruction Pointer) 存放一个指针,指向下一条等待执行的指令地址 ESP 栈指针寄存器(Extended St ...

  10. 转载——CLR标量函数、表值函数和聚合函数(UDA)

    本节主要介绍使用CLR创建标量函数,表值函数和聚合函数. 所谓标量函数指的就是此函数只返回一个值.表值函数返回值是一个表.聚合函数是在select语句中使用的,用来聚合一个结果集,类似于Sum()或是 ...