Merge pull request #227 from luhuaei/master

Pdf-viewer: multi annot type.
master
Andy Stewart 6 years ago committed by GitHub
commit f29430fddd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 132
      app/pdf-viewer/buffer.py
  2. 5
      eaf.el

@ -21,7 +21,7 @@
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QRect, QEvent
from PyQt5.QtGui import QColor, QPixmap, QImage, QFont
from PyQt5.QtGui import QColor, QPixmap, QImage, QFont, QCursor
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget
from core.buffer import Buffer
@ -138,7 +138,7 @@ class AppBuffer(Buffer):
def action_quit(self):
if self.buffer_widget.is_mark_search:
self.buffer_widget.cleanup_search()
if self.buffer_widget.is_mark_link:
if self.buffer_widget.is_jump_link:
self.buffer_widget.cleanup_links()
if self.buffer_widget.is_select_mode:
self.buffer_widget.cleanup_select()
@ -166,8 +166,21 @@ class AppBuffer(Buffer):
def add_annot_highlight(self):
if self.buffer_widget.is_select_mode:
self.buffer_widget.highlight_select_char_area()
self.buffer_widget.cleanup_select()
self.buffer_widget.annot_select_char_area("highlight")
def add_annot_strikeout_or_delete_annot(self):
if self.buffer_widget.is_select_mode:
self.buffer_widget.annot_select_char_area("strikeout")
elif self.buffer_widget.is_hover_annot:
self.buffer_widget.annot_handler("delete")
def add_annot_underline(self):
if self.buffer_widget.is_select_mode:
self.buffer_widget.annot_select_char_area("underline")
def add_annot_squiggly(self):
if self.buffer_widget.is_select_mode:
self.buffer_widget.annot_select_char_area("squiggly")
class PdfViewerWidget(QWidget):
translate_double_click_word = QtCore.pyqtSignal(str)
@ -202,6 +215,7 @@ class PdfViewerWidget(QWidget):
self.mark_link_annot_cache_dict = {}
#jump link
self.is_jump_link = False
self.jump_link_key_cache_dict = {}
self.jump_link_annot_cache_dict = {}
@ -217,8 +231,12 @@ class PdfViewerWidget(QWidget):
self.last_char_rect_index = None
self.last_char_page_index = None
self.select_area_annot_cache_dict = {}
self.select_area_annot_quad_cache_dict = {}
self.char_dict = {k:None for k in range(self.page_total_number)}
# annot
self.is_hover_annot = False
# Init scroll attributes.
self.scroll_step = 20
self.scroll_offset = 0
@ -291,11 +309,9 @@ class PdfViewerWidget(QWidget):
self.page_cache_scale = scale
self.page_cache_trans = fitz.Matrix(scale, scale)
page = self.document[index]
if self.is_mark_link:
page = self.add_mark_link(index)
else:
self.delete_all_mark_link()
page = self.document[index]
# follow page search text
if self.is_mark_search:
@ -524,8 +540,12 @@ class PdfViewerWidget(QWidget):
# Re-render page.
self.update()
def toggle_mark_link(self):
self.is_mark_link = not self.is_mark_link
def toggle_mark_link(self): # mark_link will add underline mark on link, using prompt link position.
if self.is_mark_link:
self.cleanup_mark_link()
else:
self.is_mark_link = True
self.page_cache_pixmap_dict.clear()
self.update()
@ -540,14 +560,14 @@ class PdfViewerWidget(QWidget):
self.mark_link_annot_cache_dict[index] = annot_list
return page
def delete_all_mark_link(self):
if (not self.is_mark_link) and self.mark_link_annot_cache_dict:
def cleanup_mark_link(self):
if self.mark_link_annot_cache_dict:
for index in self.mark_link_annot_cache_dict.keys():
page = self.document[index]
for annot in self.mark_link_annot_cache_dict[index]:
page.deleteAnnot(annot)
self.is_mark_link = False
self.mark_link_annot_cache_dict.clear()
self.update()
def generate_random_key(self, count):
letters = "ASDFHJKLQWEIOP"
@ -598,6 +618,7 @@ class PdfViewerWidget(QWidget):
self.jump_link_annot_cache_dict.clear()
def jump_to_link(self, key):
self.is_jump_link = True
key = str(key).upper()
if key in self.jump_link_key_cache_dict:
link = self.jump_link_key_cache_dict[key]
@ -608,7 +629,7 @@ class PdfViewerWidget(QWidget):
self.message_to_emacs.emit("Landed on Page " + str(link["page"] + 1))
def cleanup_links(self):
self.is_mark_link = False
self.is_jump_link = False
self.delete_all_mark_jump_link_tips()
self.page_cache_pixmap_dict.clear()
@ -697,9 +718,9 @@ class PdfViewerWidget(QWidget):
return chars_list
def get_char_rect_index(self, event):
def get_char_rect_index(self):
offset = 15
ex, ey, page_index = self.get_event_absolute_position(event)
ex, ey, page_index = self.get_cursor_absolute_position()
if ex and ey and page_index:
rect = fitz.Rect(ex, ey, ex + offset, ey + offset)
for char_index, char in enumerate(self.char_dict[page_index]):
@ -746,10 +767,23 @@ class PdfViewerWidget(QWidget):
string += "\n\n" # add new line on page end.
return string
def highlight_select_char_area(self):
for key in self.select_area_annot_cache_dict.keys():
self.select_area_annot_cache_dict[key] = None
def annot_select_char_area(self, annot_type="highlight"):
self.cleanup_select() # needs first cleanup select highlight mark.
for page_index, quad_list in self.select_area_annot_quad_cache_dict.items():
page = self.document[page_index]
if annot_type == "highlight":
new_annot = page.addHighlightAnnot(quad_list)
elif annot_type == "strikeout":
new_annot = page.addStrikeoutAnnot(quad_list)
elif annot_type == "underline":
new_annot = page.addUnderlineAnnot(quad_list)
elif annot_type == "squiggly":
new_annot = page.addSquigglyAnnot(quad_list)
new_annot.parent = page
self.document.saveIncr()
self.select_area_annot_quad_cache_dict.clear()
def cleanup_select(self):
self.is_select_mode = False
@ -797,6 +831,7 @@ class PdfViewerWidget(QWidget):
# refresh annot
self.select_area_annot_cache_dict[page_index] = annot
self.select_area_annot_quad_cache_dict[page_index] = quad_list
self.page_cache_pixmap_dict.clear()
self.update()
@ -813,6 +848,40 @@ class PdfViewerWidget(QWidget):
self.start_char_page_index = None
self.start_char_rect_index = None
def hover_annot(self):
ex, ey, page_index = self.get_cursor_absolute_position()
page = self.document[page_index]
annots = page.annots()
if not annots:
return None
annot = None # annots is generator, will probably cause annot don't assign
for annot in annots:
if annot.rect.contains(fitz.Point(ex, ey)):
self.is_hover_annot = True
annot.setOpacity(0.5)
self.message_to_emacs.emit("[d]Delete Annot")
else:
annot.setOpacity(1) # restore annot
self.is_hover_annot = False
annot.update()
self.page_cache_pixmap_dict.clear()
self.update()
return page, annot
def annot_handler(self, action=None):
page, annot = self.hover_annot()
if annot.parent:
if action == "delete":
page.deleteAnnot(annot)
self.document.saveIncr()
self.page_cache_pixmap_dict.clear()
self.update()
def jump_to_page(self, page_num):
self.update_scroll_offset(min(max(self.scale * (int(page_num) - 1) * self.page_height, 0), self.max_scroll_offset()))
@ -824,10 +893,10 @@ class PdfViewerWidget(QWidget):
self.scroll_offset = new_offset
self.update()
def get_event_absolute_position(self, event):
def get_cursor_absolute_position(self):
start_page_index = self.get_start_page_index()
last_page_index = self.get_last_page_index()
pos = event.pos()
ex, ey = QCursor.pos().x(), QCursor.pos().y()
for index in list(range(start_page_index, last_page_index)):
if index < self.page_total_number:
@ -835,21 +904,21 @@ class PdfViewerWidget(QWidget):
render_x = int((self.rect().width() - render_width) / 2)
# computer absolute coordinate of page
x = (pos.x() - render_x) * 1.0 / self.scale
if pos.y() + self.scroll_offset < (start_page_index + 1) * self.scale * self.page_height:
x = (ex - render_x) * 1.0 / self.scale
if ey + self.scroll_offset < (start_page_index + 1) * self.scale * self.page_height:
page_offset = self.scroll_offset - start_page_index * self.scale * self.page_height
page_index = index
else:
# if display two pages, pos.y() will add page_padding
page_offset = self.scroll_offset - (start_page_index + 1) * self.scale * self.page_height - self.page_padding
page_index = index + 1
y = (pos.y() + page_offset) * 1.0 / self.scale
y = (ey + page_offset) * 1.0 / self.scale
return x, y, page_index
return None, None, None
def get_event_link(self, event):
ex, ey, page_index = self.get_event_absolute_position(event)
def get_event_link(self):
ex, ey, page_index = self.get_cursor_absolute_position()
if page_index is None:
return None
@ -862,8 +931,8 @@ class PdfViewerWidget(QWidget):
return None
def get_double_click_word(self, event):
ex, ey, page_index = self.get_event_absolute_position(event)
def get_double_click_word(self):
ex, ey, page_index = self.get_cursor_absolute_position()
if page_index is None:
return None
page = self.document[page_index]
@ -879,17 +948,20 @@ class PdfViewerWidget(QWidget):
def eventFilter(self, obj, event):
if event.type() == QEvent.MouseMove:
if self.is_select_mode:
rect_index, page_index = self.get_char_rect_index(event)
rect_index, page_index = self.get_char_rect_index()
if rect_index and page_index:
if self.start_char_rect_index is None or self.start_char_page_index is None:
self.start_char_rect_index, self.start_char_page_index = rect_index, page_index
else:
self.last_char_rect_index, self.last_char_page_index = rect_index, page_index
self.mark_select_char_area()
else:
self.hover_annot()
elif event.type() == QEvent.MouseButtonPress:
if event.button() == Qt.LeftButton:
event_link = self.get_event_link(event)
event_link = self.get_event_link()
if event_link:
self.jump_to_page(event_link["page"] + 1)
@ -897,7 +969,7 @@ class PdfViewerWidget(QWidget):
if self.is_mark_search:
self.cleanup_search()
if event.button() == Qt.RightButton:
double_click_word = self.get_double_click_word(event)
double_click_word = self.get_double_click_word()
if double_click_word:
self.translate_double_click_word.emit(double_click_word)
elif event.button() == Qt.LeftButton:

@ -314,7 +314,10 @@ Try not to modify this alist directly. Use `eaf-setq' to modify instead."
("M-w" . "copy_select")
("C-s" . "search_text_forward")
("C-r" . "search_text_backward")
("h" . "add_annot_highlight"))
("h" . "add_annot_highlight")
("u" . "add_annot_underline")
("s" . "add_annot_squiggly")
("d" . "add_annot_strikeout_or_delete_annot"))
"The keybinding of EAF PDF Viewer."
:type 'cons)

Loading…
Cancel
Save