Remove unused code

This commit is contained in:
Kovid Goyal 2016-10-30 21:12:57 +05:30
parent 2b7d3d0a54
commit 68bae59ae8
2 changed files with 0 additions and 403 deletions

View File

@ -1,294 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from functools import lru_cache
from collections import Counter, deque, defaultdict
from itertools import chain
from PyQt5.QtCore import QObject, pyqtSignal, Qt, QTimer, QRect
from PyQt5.QtGui import QPixmap, QRegion, QPainter, QPen, QColor, QFontMetrics, QFont
from .config import build_ansi_color_tables, fg_color_table, bg_color_table
from .data_types import Cursor, COL_SHIFT, COL_MASK, as_color, BOLD_MASK, ITALIC_MASK
from .screen import wrap_cursor_position
from .tracker import merge_ranges
from .utils import set_current_font_metrics
def ascii_width(fm: QFontMetrics) -> int:
ans = 0
for i in range(32, 128):
ans = max(ans, fm.widthChar(chr(i)))
return ans
@lru_cache(maxsize=2**11)
def pixmap_for_text(ch, cc, color, default_fg, font, w, h, baseline):
p = QPixmap(w, h)
p.fill(Qt.transparent)
fg = as_color(color & COL_MASK, fg_color_table()) or default_fg
painter = QPainter(p)
painter.setFont(font)
painter.setPen(QPen(QColor(*fg)))
painter.setRenderHints(QPainter.TextAntialiasing | QPainter.Antialiasing)
painter.drawText(0, baseline, chr(ch) + (cc or ''))
painter.end()
return p
class Renderer(QObject):
update_required = pyqtSignal()
relayout_lines = pyqtSignal(object, object)
cells_per_line = 80
lines_per_screen = 24
last_painted_cursor_at = 0, 0
_has_focus = True
def __init__(self, screen, dpix, dpiy, parent=None):
QObject.__init__(self, parent)
self.dpix, self.dpiy = dpix, dpiy
self.screen = screen
screen.change_default_color.connect(self.change_default_color)
self.bufpix = QPixmap(10, 10)
self.pending_changes = deque()
self.debounce_update_timer = t = QTimer(self)
t.setSingleShot(True)
t.setInterval(20)
t.timeout.connect(self.do_render)
self.cursor = Cursor()
def apply_opts(self, opts):
pixmap_for_text.cache_clear()
build_ansi_color_tables(opts)
self.opts = opts
self.default_bg = self.original_bg = QColor(opts.background)
self.default_fg = self.original_fg = QColor(opts.foreground).getRgb()[:3]
self.current_font = f = QFont(opts.font_family)
f.setPointSizeF(opts.font_size)
self.font_metrics = fm = QFontMetrics(f)
self.bold_font = b = QFont(f)
b.setBold(True)
self.italic_font = i = QFont(f)
i.setItalic(True)
self.bi_font = bi = QFont(i)
bi.setBold(True)
self.cell_height = fm.lineSpacing()
self.cell_width = ascii_width(fm)
set_current_font_metrics(fm, self.cell_width)
self.baseline_offset = fm.ascent()
self.cursor_color = c = QColor(opts.cursor)
c.setAlphaF(opts.cursor_opacity)
def resize(self, size):
self.bufpix = QPixmap(size)
self.bufpix.fill(self.default_bg)
previous, self.cells_per_line = self.cells_per_line, size.width() // self.cell_width
previousl, self.lines_per_screen = self.lines_per_screen, size.height() // self.cell_height
self.hmargin = (size.width() - self.cells_per_line * self.cell_width) // 2
self.vmargin = (size.height() % self.cell_height) // 2
self.line_positions = tuple(self.vmargin + i * self.cell_height for i in range(self.lines_per_screen))
self.cell_positions = tuple(self.hmargin + i * self.cell_width for i in range(self.cells_per_line))
self.row_rects = {lnum: QRect(self.hmargin, self.line_positions[lnum], self.cell_width *
self.cells_per_line, self.cell_height) for lnum in range(self.lines_per_screen)}
self.col_rects = {cnum: QRect(self.cell_positions[cnum], self.vmargin, self.cell_width,
self.cell_height * self.lines_per_screen) for cnum in range(self.cells_per_line)}
self.cell_rects = {
lnum: {cnum: self.col_rects[cnum].intersected(self.row_rects[lnum]) for cnum in self.col_rects}
for lnum in self.row_rects
}
self.line_width = self.cells_per_line * self.cell_width
if (previous, previousl) != (self.cells_per_line, self.lines_per_screen):
self.screen.resize(self.lines_per_screen, self.cells_per_line)
self.relayout_lines.emit(self.cells_per_line, self.lines_per_screen)
self.dirtied()
def dirtied(self):
self.update_screen({'screen': True})
def size(self):
return self.bufpix.size()
def render(self, painter):
painter.drawPixmap(0, 0, self.bufpix)
def change_default_color(self, which, val):
if which in ('fg', 'bg'):
if not val:
setattr(self, 'default_' + which, getattr(self, 'original_' + which))
self.dirtied()
else:
val = QColor(val)
if val.isValid():
if which == 'fg':
self.default_fg = val.getRgb()[:3]
else:
self.default_bg = val
self.dirtied()
def update_screen(self, changes):
self.pending_changes.append(changes)
if not self.debounce_update_timer.isActive():
self.debounce_update_timer.start()
def wrap_cursor_pos(self):
self.cursorx, self.cursory = wrap_cursor_position(self.cursor.x, self.cursor.y, self.lines_per_screen, self.cells_per_line)
def set_has_focus(self, yes):
if yes != self._has_focus:
self._has_focus = yes
self.wrap_cursor_pos()
self.update_screen({'screen': False, 'lines': set(), 'cells': {self.cursory: {(self.cursorx, self.cursorx)}}})
def line(self, lnum):
return self.screen.line(lnum)
def common_bg_color(self):
c = Counter()
for rdiv in range(1, 4):
lnum = int(self.lines_per_screen * rdiv / 4)
for cdiv in range(1, 4):
cnum = int(self.cells_per_line * cdiv / 4)
bgcol = self.line(lnum).bgcolor(cnum)
c[bgcol] += 1
return c.most_common(1)[0][0]
def do_render(self):
dirty_lines = set()
dirty_cell_ranges = defaultdict(set)
screen_dirtied = False
while self.pending_changes:
c = self.pending_changes.popleft()
self.cursor = c.get('cursor') or self.cursor
if not screen_dirtied:
if c['screen']:
screen_dirtied = True
continue
dirty_lines |= c['lines']
for l, ranges in c['cells'].items():
if l not in dirty_lines:
for r in ranges:
dirty_cell_ranges[l].add(r)
if screen_dirtied:
dirty_cell_ranges = {}
dirty_lines = tuple(range(self.lines_per_screen))
else:
dirty_cell_ranges = {l: tuple(merge_ranges(r)) for l, r in dirty_cell_ranges.items() if l not in dirty_lines}
self.paint(dirty_lines, dirty_cell_ranges, screen_dirtied)
self.update_required.emit()
def calculate_dirty_region(self, dirty_lines, dirty_cell_ranges):
ans = QRegion()
for lnum in dirty_lines:
ans += self.row_rects[lnum]
for lnum, ranges in dirty_cell_ranges.items():
lrect = self.cell_rects[lnum]
for start, stop in ranges:
for cnum in range(start, stop + 1):
ans += lrect[cnum]
return ans
def paint(self, dirty_lines, dirty_cell_ranges, screen_dirtied):
self.current_bgcol = self.common_bg_color()
bg = self.default_bg
if self.current_bgcol & 0xff:
cbg = as_color(self.current_bgcol, bg_color_table())
if cbg:
bg = QColor(*cbg)
self.wrap_cursor_pos()
self.cursor_painted = False
self.old_cursorx, self.old_cursory = self.last_painted_cursor_at
self.cursor_moved = self.old_cursorx != self.cursorx or self.old_cursory != self.cursory
region = QRegion(self.bufpix.rect()) if screen_dirtied else self.calculate_dirty_region(dirty_lines, dirty_cell_ranges)
if self.cursor_moved:
r = QRect(self.cell_positions[self.old_cursorx], self.line_positions[self.old_cursory], self.cell_width, self.cell_height)
if region.contains(r):
self.cursor_moved = False
else:
region += r
p = QPainter(self.bufpix)
p.save()
p.setClipRegion(region)
p.fillRect(self.bufpix.rect(), bg)
p.restore()
for lnum in dirty_lines:
self.paint_line(p, lnum, range(self.cells_per_line))
for lnum, ranges in dirty_cell_ranges.items():
self.paint_line(p, lnum, chain.from_iterable(range(start, stop + 1) for start, stop in ranges))
if not self.cursor_painted:
self.paint_cell(p, self.line(self.cursory), self.cursory, self.cursorx)
if self.cursor_moved:
self.paint_cell(p, self.line(self.old_cursory), self.old_cursory, self.old_cursorx)
p.end()
def paint_line(self, painter, lnum, cell_range):
line = self.line(lnum)
for cnum in cell_range:
self.paint_cell(painter, line, lnum, cnum)
def paint_cell(self, painter, line, lnum, cnum):
paint_cursor = False
if not self.cursor_painted:
self.cursor_painted = paint_cursor = lnum == self.cursory and cnum == self.cursorx
ch, attrs, colors = line.basic_cell_data(cnum)
x, y = self.cell_positions[cnum], self.line_positions[lnum]
bgcol = colors >> COL_SHIFT
if bgcol != self.current_bgcol:
bg = as_color(colors >> COL_SHIFT, bg_color_table())
if bg is not None:
r = QRect(x, y, self.cell_width, self.cell_height)
painter.fillRect(r, QColor(*bg))
if paint_cursor:
self.paint_cursor(painter, cnum, lnum)
if ch == 0 or ch == 32:
# An empty cell
pass
else:
font = self.current_font
b, i = attrs & BOLD_MASK, attrs & ITALIC_MASK
if b:
font = self.bi_font if i else self.bold_font
elif i:
font = self.italic_font
p = pixmap_for_text(ch, line.combining_chars.get(cnum), colors & COL_MASK,
self.default_fg, font, self.cell_width * 2, self.cell_height, self.baseline_offset)
painter.drawPixmap(x, y, p)
def paint_cursor(self, painter, x, y):
self.last_painted_cursor_at = x, y
r = QRect(self.cell_positions[x], self.line_positions[y], self.cell_width, self.cell_height)
cc = self.cursor_color
if self.cursor.color:
q = QColor(self.cursor.color)
if q.isValid():
cc = q
cc.setAlphaF(self.opts.cursor_opacity)
def width(w=2, vert=True):
dpi = self.dpix if vert else self.dpiy
return int(w * dpi / 72)
if self._has_focus:
cs = self.cursor.shape or self.opts.cursor_shape
if cs == 'block':
painter.fillRect(r, cc)
elif cs == 'beam':
w = width(1.5)
painter.fillRect(r.left(), r.top(), w, self.cell_height, cc)
elif cs == 'underline':
y = r.top() + self.font_metrics.underlinePos() + self.baseline_offset
w = width(vert=False)
painter.fillRect(r.left(), min(y, r.bottom() - w), self.cell_width, w, cc)
else:
painter.setPen(QPen(cc))
painter.drawRect(r)

View File

@ -1,109 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from PyQt5.QtCore import pyqtSignal, QTimer, Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget, QApplication
from .config import Options
from .tracker import ChangeTracker
from .keys import key_event_to_data
from .screen import Screen
from .render import Renderer
from pyte.streams import Stream, DebugStream
from pyte import modes as mo
class TerminalWidget(QWidget):
relayout_lines = pyqtSignal(object, object)
write_to_child = pyqtSignal(object)
title_changed = pyqtSignal(object)
icon_changed = pyqtSignal(object)
send_data_to_child = pyqtSignal(object)
def __init__(self, opts: Options, parent: QWidget=None, dump_commands: bool=False):
QWidget.__init__(self, parent)
self.setAttribute(Qt.WA_OpaquePaintEvent, True)
self.setAutoFillBackground(False)
self.setFocusPolicy(Qt.WheelFocus)
self.debounce_resize_timer = t = QTimer(self)
t.setSingleShot(True)
t.setInterval(50)
t.timeout.connect(self.do_layout)
self.tracker = ChangeTracker(self)
sclass = DebugStream if dump_commands else Stream
self.screen = Screen(opts, self.tracker, parent=self)
for s in 'write_to_child title_changed icon_changed'.split():
getattr(self.screen, s).connect(getattr(self, s))
self.stream = sclass(self.screen)
self.feed = self.stream.feed
self.renderer = Renderer(self.screen, self.logicalDpiX(), self.logicalDpiY(), self)
self.tracker.dirtied.connect(self.renderer.update_screen)
self.renderer.update_required.connect(self.update_required)
self.renderer.relayout_lines.connect(self.relayout_lines)
self.apply_opts(opts)
def update_required(self):
self.update()
def apply_opts(self, opts):
self.screen.apply_opts(opts)
self.opts = opts
self.renderer.apply_opts(opts)
self.do_layout()
def do_layout(self):
self.renderer.resize(self.size())
self.update()
def resizeEvent(self, ev):
self.debounce_resize_timer.start()
def paintEvent(self, ev):
if self.size() != self.renderer.size():
return
p = QPainter(self)
self.renderer.render(p)
p.end()
def keyPressEvent(self, ev):
mods = ev.modifiers()
if mods & Qt.ControlModifier and mods & Qt.ShiftModifier:
ev.accept()
return # Terminal shortcuts
data = key_event_to_data(ev, mods)
if data:
self.send_data_to_child.emit(data)
ev.accept()
return
return QWidget.keyPressEvent(self, ev)
def mousePressEvent(self, ev):
if ev.button() == Qt.MiddleButton:
c = QApplication.clipboard()
if c.supportsSelection():
text = c.text(c.Selection)
if text:
text = text.encode('utf-8')
if self.screen.in_bracketed_paste_mode:
text = mo.BRACKETED_PASTE_START + text + mo.BRACKETED_PASTE_END
self.send_data_to_child.emit(text)
ev.accept()
return
return QWidget.mousePressEvent(self, ev)
def focusInEvent(self, ev):
if self.screen.enable_focus_tracking:
self.send_data_to_child.emit(b'\x1b[I')
self.renderer.set_has_focus(True)
return QWidget.focusInEvent(self, ev)
def focusOutEvent(self, ev):
if self.screen.enable_focus_tracking:
self.send_data_to_child.emit(b'\x1b[O')
self.renderer.set_has_focus(False)
return QWidget.focusOutEvent(self, ev)