import subprocess
import sqlite3
from dataclasses import dataclass
from functools import lru_cache
import fitz
import regex
import os
def merge_rects(rects):
'''
Merge close rectangles in a line (e.g. rectangles corresponding to a single character or word)
'''
if len(rects) == 0:
return []
resulting_rects = [rects[0]]
y_threshold = abs(rects[0].y1 - rects[0].y0) * 0.3
def extend_last_rect(new_rect):
resulting_rects[-1].x1 = max(resulting_rects[-1].x1, new_rect.x1)
resulting_rects[-1].y0 = min(resulting_rects[-1].y0, new_rect.y0)
resulting_rects[-1].y1 = min(resulting_rects[-1].y1, new_rect.y1)
for rect in rects[1:]:
if abs(rect.y0 - resulting_rects[-1].y0) < y_threshold:
extend_last_rect(rect)
else:
resulting_rects.append(rect)
return resulting_rects
class Sioyek:
def __init__(self, sioyek_path, local_database_path=None, shared_database_path=None):
self.path = sioyek_path
self.is_dummy_mode = False
self.local_database = None
self.shared_database = None
self.cached_path_hash_map = None
if local_database_path != None:
self.local_database_path = local_database_path
self.local_database = sqlite3.connect(self.local_database_path)
if shared_database_path != None:
self.shared_database_path = shared_database_path
self.shared_database = sqlite3.connect(self.shared_database_path)
def get_local_database(self):
return self.local_database
def get_shared_database(self):
return self.shared_database
def set_dummy_mode(self, mode):
self.is_dummy_mode = mode
def get_path_hash_map(self):
if self.cached_path_hash_map == None:
query = 'SELECT * from document_hash'
cursor = self.get_local_database().execute(query)
results = cursor.fetchall()
res = dict()
for _, path, hash_ in results:
res[path] = hash_
self.cached_path_hash_map = res
return self.cached_path_hash_map
def run_command(self, command_name, text=None, focus=False):
if text == None:
params = [self.path, '--execute-command', command_name]
else:
params = [self.path, '--execute-command', command_name, '--execute-command-data', text]
if focus == False:
params.append('--nofocus')
if self.is_dummy_mode:
print('dummy mode, executing: ', params)
else:
subprocess.run(params)
def goto_begining(self, focus=False):
data = None
self.run_command("goto_begining", data, focus=focus)
def goto_end(self, focus=False):
data = None
self.run_command("goto_end", data, focus=focus)
def goto_definition(self, focus=False):
data = None
self.run_command("goto_definition", data, focus=focus)
def overview_definition(self, focus=False):
data = None
self.run_command("overview_definition", data, focus=focus)
def portal_to_definition(self, focus=False):
data = None
self.run_command("portal_to_definition", data, focus=focus)
def next_item(self, focus=False):
data = None
self.run_command("next_item", data, focus=focus)
def previous_item(self, focus=False):
data = None
self.run_command("previous_item", data, focus=focus)
def set_mark(self, symbol, focus=False):
data = symbol
self.run_command("set_mark", data, focus=focus)
def goto_mark(self, symbol, focus=False):
data = symbol
self.run_command("goto_mark", data, focus=focus)
def goto_page_with_page_number(self, text, focus=False):
data = text
self.run_command("goto_page_with_page_number", data, focus=focus)
def search(self, text, focus=False):
data = text
self.run_command("search", data, focus=focus)
def ranged_search(self, text, focus=False):
data = text
self.run_command("ranged_search", data, focus=focus)
def chapter_search(self, text, focus=False):
data = text
self.run_command("chapter_search", data, focus=focus)
def move_down(self, focus=False):
data = None
self.run_command("move_down", data, focus=focus)
def move_up(self, focus=False):
data = None
self.run_command("move_up", data, focus=focus)
def move_left(self, focus=False):
data = None
self.run_command("move_left", data, focus=focus)
def move_right(self, focus=False):
data = None
self.run_command("move_right", data, focus=focus)
def zoom_in(self, focus=False):
data = None
self.run_command("zoom_in", data, focus=focus)
def zoom_out(self, focus=False):
data = None
self.run_command("zoom_out", data, focus=focus)
def fit_to_page_width(self, focus=False):
data = None
self.run_command("fit_to_page_width", data, focus=focus)
def fit_to_page_height(self, focus=False):
data = None
self.run_command("fit_to_page_height", data, focus=focus)
def fit_to_page_height_smart(self, focus=False):
data = None
self.run_command("fit_to_page_height_smart", data, focus=focus)
def fit_to_page_width_smart(self, focus=False):
data = None
self.run_command("fit_to_page_width_smart", data, focus=focus)
def next_page(self, focus=False):
data = None
self.run_command("next_page", data, focus=focus)
def previous_page(self, focus=False):
data = None
self.run_command("previous_page", data, focus=focus)
def open_document(self, filename, focus=False):
data = filename
self.run_command("open_document", data, focus=focus)
def debug(self, focus=False):
data = None
self.run_command("debug", data, focus=focus)
def add_bookmark(self, text, focus=False):
data = text
self.run_command("add_bookmark", data, focus=focus)
def add_highlight(self, symbol, focus=False):
data = symbol
self.run_command("add_highlight", data, focus=focus)
def goto_toc(self, focus=False):
data = None
self.run_command("goto_toc", data, focus=focus)
def goto_highlight(self, focus=False):
data = None
self.run_command("goto_highlight", data, focus=focus)
def goto_bookmark(self, focus=False):
data = None
self.run_command("goto_bookmark", data, focus=focus)
def goto_bookmark_g(self, focus=False):
data = None
self.run_command("goto_bookmark_g", data, focus=focus)
def goto_highlight_g(self, focus=False):
data = None
self.run_command("goto_highlight_g", data, focus=focus)
def goto_highlight_ranged(self, focus=False):
data = None
self.run_command("goto_highlight_ranged", data, focus=focus)
def link(self, focus=False):
data = None
self.run_command("link", data, focus=focus)
def portal(self, focus=False):
data = None
self.run_command("portal", data, focus=focus)
def next_state(self, focus=False):
data = None
self.run_command("next_state", data, focus=focus)
def prev_state(self, focus=False):
data = None
self.run_command("prev_state", data, focus=focus)
def pop_state(self, focus=False):
data = None
self.run_command("pop_state", data, focus=focus)
def test_command(self, focus=False):
data = None
self.run_command("test_command", data, focus=focus)
def delete_link(self, focus=False):
data = None
self.run_command("delete_link", data, focus=focus)
def delete_portal(self, focus=False):
data = None
self.run_command("delete_portal", data, focus=focus)
def delete_bookmark(self, focus=False):
data = None
self.run_command("delete_bookmark", data, focus=focus)
def delete_highlight(self, focus=False):
data = None
self.run_command("delete_highlight", data, focus=focus)
def goto_link(self, focus=False):
data = None
self.run_command("goto_link", data, focus=focus)
def goto_portal(self, focus=False):
data = None
self.run_command("goto_portal", data, focus=focus)
def edit_link(self, focus=False):
data = None
self.run_command("edit_link", data, focus=focus)
def edit_portal(self, focus=False):
data = None
self.run_command("edit_portal", data, focus=focus)
def open_prev_doc(self, focus=False):
data = None
self.run_command("open_prev_doc", data, focus=focus)
def open_document_embedded(self, focus=False):
data = None
self.run_command("open_document_embedded", data, focus=focus)
def open_document_embedded_from_current_path(self, focus=False):
data = None
self.run_command("open_document_embedded_from_current_path", data, focus=focus)
def copy(self, focus=False):
data = None
self.run_command("copy", data, focus=focus)
def toggle_fullscreen(self, focus=False):
data = None
self.run_command("toggle_fullscreen", data, focus=focus)
def toggle_one_window(self, focus=False):
data = None
self.run_command("toggle_one_window", data, focus=focus)
def toggle_highlight(self, focus=False):
data = None
self.run_command("toggle_highlight", data, focus=focus)
def toggle_synctex(self, focus=False):
data = None
self.run_command("toggle_synctex", data, focus=focus)
def command(self, focus=False):
data = None
self.run_command("command", data, focus=focus)
def external_search(self, symbol, focus=False):
data = symbol
self.run_command("external_search", data, focus=focus)
def open_selected_url(self, focus=False):
data = None
self.run_command("open_selected_url", data, focus=focus)
def screen_down(self, focus=False):
data = None
self.run_command("screen_down", data, focus=focus)
def screen_up(self, focus=False):
data = None
self.run_command("screen_up", data, focus=focus)
def next_chapter(self, focus=False):
data = None
self.run_command("next_chapter", data, focus=focus)
def prev_chapter(self, focus=False):
data = None
self.run_command("prev_chapter", data, focus=focus)
def toggle_dark_mode(self, focus=False):
data = None
self.run_command("toggle_dark_mode", data, focus=focus)
def toggle_presentation_mode(self, focus=False):
data = None
self.run_command("toggle_presentation_mode", data, focus=focus)
def toggle_mouse_drag_mode(self, focus=False):
data = None
self.run_command("toggle_mouse_drag_mode", data, focus=focus)
def close_window(self, focus=False):
data = None
self.run_command("close_window", data, focus=focus)
def quit(self, focus=False):
data = None
self.run_command("quit", data, focus=focus)
def open_link(self, text, focus=False):
data = text
self.run_command("open_link", data, focus=focus)
def keyboard_select(self, text, focus=False):
data = text
self.run_command("keyboard_select", data, focus=focus)
def keyboard_smart_jump(self, text, focus=False):
data = text
self.run_command("keyboard_smart_jump", data, focus=focus)
def keyboard_overview(self, text, focus=False):
data = text
self.run_command("keyboard_overview", data, focus=focus)
def keys(self, focus=False):
data = None
self.run_command("keys", data, focus=focus)
def keys_user(self, focus=False):
data = None
self.run_command("keys_user", data, focus=focus)
def prefs(self, focus=False):
data = None
self.run_command("prefs", data, focus=focus)
def prefs_user(self, focus=False):
data = None
self.run_command("prefs_user", data, focus=focus)
def import_(self, focus=False):
data = None
self.run_command("import", data, focus=focus)
def export(self, focus=False):
data = None
self.run_command("export", data, focus=focus)
def enter_visual_mark_mode(self, focus=False):
data = None
self.run_command("enter_visual_mark_mode", data, focus=focus)
def move_visual_mark_down(self, focus=False):
data = None
self.run_command("move_visual_mark_down", data, focus=focus)
def move_visual_mark_up(self, focus=False):
data = None
self.run_command("move_visual_mark_up", data, focus=focus)
def set_page_offset(self, text, focus=False):
data = text
self.run_command("set_page_offset", data, focus=focus)
def toggle_visual_scroll(self, focus=False):
data = None
self.run_command("toggle_visual_scroll", data, focus=focus)
def toggle_horizontal_scroll_lock(self, focus=False):
data = None
self.run_command("toggle_horizontal_scroll_lock", data, focus=focus)
def toggle_custom_color(self, focus=False):
data = None
self.run_command("toggle_custom_color", data, focus=focus)
def execute(self, text, focus=False):
data = text
self.run_command("execute", data, focus=focus)
def execute_predefined_command(self, symbol, focus=False):
data = symbol
self.run_command("execute_predefined_command", data, focus=focus)
def embed_annotations(self, focus=False):
data = None
self.run_command("embed_annotations", data, focus=focus)
def copy_window_size_config(self, focus=False):
data = None
self.run_command("copy_window_size_config", data, focus=focus)
def toggle_select_highlight(self, focus=False):
data = None
self.run_command("toggle_select_highlight", data, focus=focus)
def set_select_highlight_type(self, symbol, focus=False):
data = symbol
self.run_command("set_select_highlight_type", data, focus=focus)
def open_last_document(self, focus=False):
data = None
self.run_command("open_last_document", data, focus=focus)
def toggle_window_configuration(self, focus=False):
data = None
self.run_command("toggle_window_configuration", data, focus=focus)
def prefs_user_all(self, focus=False):
data = None
self.run_command("prefs_user_all", data, focus=focus)
def keys_user_all(self, focus=False):
data = None
self.run_command("keys_user_all", data, focus=focus)
def fit_to_page_width_ratio(self, focus=False):
data = None
self.run_command("fit_to_page_width_ratio", data, focus=focus)
def smart_jump_under_cursor(self, focus=False):
data = None
self.run_command("smart_jump_under_cursor", data, focus=focus)
def overview_under_cursor(self, focus=False):
data = None
self.run_command("overview_under_cursor", data, focus=focus)
def close_overview(self, focus=False):
data = None
self.run_command("close_overview", data, focus=focus)
def visual_mark_under_cursor(self, focus=False):
data = None
self.run_command("visual_mark_under_cursor", data, focus=focus)
def close_visual_mark(self, focus=False):
data = None
self.run_command("close_visual_mark", data, focus=focus)
def zoom_in_cursor(self, focus=False):
data = None
self.run_command("zoom_in_cursor", data, focus=focus)
def zoom_out_cursor(self, focus=False):
data = None
self.run_command("zoom_out_cursor", data, focus=focus)
def goto_left(self, focus=False):
data = None
self.run_command("goto_left", data, focus=focus)
def goto_left_smart(self, focus=False):
data = None
self.run_command("goto_left_smart", data, focus=focus)
def goto_right(self, focus=False):
data = None
self.run_command("goto_right", data, focus=focus)
def goto_right_smart(self, focus=False):
data = None
self.run_command("goto_right_smart", data, focus=focus)
def rotate_clockwise(self, focus=False):
data = None
self.run_command("rotate_clockwise", data, focus=focus)
def rotate_counterclockwise(self, focus=False):
data = None
self.run_command("rotate_counterclockwise", data, focus=focus)
def goto_next_highlight(self, focus=False):
data = None
self.run_command("goto_next_highlight", data, focus=focus)
def goto_prev_highlight(self, focus=False):
data = None
self.run_command("goto_prev_highlight", data, focus=focus)
def goto_next_highlight_of_type(self, focus=False):
data = None
self.run_command("goto_next_highlight_of_type", data, focus=focus)
def goto_prev_highlight_of_type(self, focus=False):
data = None
self.run_command("goto_prev_highlight_of_type", data, focus=focus)
def add_highlight_with_current_type(self, focus=False):
data = None
self.run_command("add_highlight_with_current_type", data, focus=focus)
def enter_password(self, text, focus=False):
data = text
self.run_command("enter_password", data, focus=focus)
def toggle_fastread(self, focus=False):
data = None
self.run_command("toggle_fastread", data, focus=focus)
def goto_top_of_page(self, focus=False):
data = None
self.run_command("goto_top_of_page", data, focus=focus)
def goto_bottom_of_page(self, focus=False):
data = None
self.run_command("goto_bottom_of_page", data, focus=focus)
def new_window(self, focus=False):
data = None
self.run_command("new_window", data, focus=focus)
def toggle_statusbar(self, focus=False):
data = None
self.run_command("toggle_statusbar", data, focus=focus)
def reload(self, focus=False):
data = None
self.run_command("reload", data, focus=focus)
def synctex_under_cursor(self, focus=False):
data = None
self.run_command("synctex_under_cursor", data, focus=focus)
def set_status_string(self, text, focus=False):
data = text
self.run_command("set_status_string", data, focus=focus)
def clear_status_string(self, focus=False):
data = None
self.run_command("clear_status_string", data, focus=focus)
def toggle_titlebar(self, focus=False):
data = None
self.run_command("toggle_titlebar", data, focus=focus)
def next_preview(self, focus=False):
data = None
self.run_command("next_preview", data, focus=focus)
def previous_preview(self, focus=False):
data = None
self.run_command("previous_preview", data, focus=focus)
def goto_overview(self, focus=False):
data = None
self.run_command("goto_overview", data, focus=focus)
def portal_to_overview(self, focus=False):
data = None
self.run_command("portal_to_overview", data, focus=focus)
def goto_selected_text(self, focus=False):
data = None
self.run_command("goto_selected_text", data, focus=focus)
def get_document(self, path):
return Document(path, self)
def close(self):
self.local_database.close()
self.shared_database.close()
@dataclass
class DocumentPos:
page: int
offset_x: float
offset_y: float
@dataclass
class AbsoluteDocumentPos:
offset_x: float
offset_y: float
class Highlight:
def __init__(self, document, text, highlight_type, begin, end):
self.doc = document
self.text = text
self.highlight_type = highlight_type
self.selection_begin = begin
self.selection_end = end
def get_begin_document_pos(self):
begin_page, begin_offset_y = self.doc.absolute_to_document_y(self.selection_begin[1])
return DocumentPos(begin_page, self.selection_begin[0], begin_offset_y)
def get_end_document_pos(self):
end_page, end_offset_y = self.doc.absolute_to_document_y(self.selection_end[1])
return DocumentPos(end_page, self.selection_end[0], end_offset_y)
def __repr__(self):
return f"Highlight of type {self.highlight_type}: {self.text}"
class Bookmark:
def __init__(self, document, description, y_offset):
self.doc = document
self.description = description
self.y_offset = y_offset
@lru_cache(maxsize=None)
def get_document_position(self):
return self.doc.absolute_to_document_y(self.y_offset)
def __repr__(self):
return f"Bookmark at {self.y_offset}: {self.description}"
class Document:
def __init__(self, path, sioyek):
self.path = path
self.doc = fitz.open(self.path)
self.set_page_dimensions()
self.sioyek = sioyek
self.cached_hash = None
def to_absolute(self, document_pos):
offset_x = document_pos.offset_x
offset_y = document_pos.offset_y + self.cum_page_heights[document_pos.page]
return AbsoluteDocumentPos(offset_x, offset_y)
def absolute_to_document_y(self, offset_y):
page = 0
while offset_y > self.page_heights[page]:
offset_y -= self.page_heights[page]
page += 1
return (page, offset_y)
def to_document(self, absolute_document_pos):
page, offset_y = self.absolute_to_document_y(absolute_document_pos.offset_y)
return DocumentPos(page, absolute_document_pos.offset_x, offset_y)
@lru_cache(maxsize=None)
def get_page(self, page_number):
return self.doc.load_page(page_number)
@lru_cache(maxsize=None)
def get_page_pdf_annotations(self, page_number):
page = self.get_page(page_number)
res = []
annot = page.first_annot
while annot != None:
res.append(annot)
annot = annot.next
return res
@lru_cache(maxsize=None)
def get_page_pdf_bookmarks(self, page_number):
def is_bookmark(annot):
return annot.type[1] == 'Text'
return [annot for annot in self.get_page_pdf_annotations(page_number) if is_bookmark(annot)]
@lru_cache(maxsize=None)
def get_page_pdf_highlights(self, page_number):
def is_highlight(annot):
return annot.type[1] == 'Highlight'
return [annot for annot in self.get_page_pdf_annotations(page_number) if is_highlight(annot)]
def embed_highlight(self, highlight, colormap=None):
docpos = highlight.get_begin_document_pos()
page = self.get_page(docpos.page)
quads = self.get_best_selection_rects(docpos.page, highlight.text, merge=True)
annot = page.add_highlight_annot(quads)
if colormap is not None:
if highlight.highlight_type in colormap.keys():
color = colormap[highlight.highlight_type]
annot.set_colors(stroke=color, fill=color)
annot.update()
def embed_bookmark(self, bookmark):
page_number, offset_y = bookmark.get_document_position()
page = self.get_page(page_number)
page.add_text_annot((0, offset_y), bookmark.description)
def embed_new_bookmarks(self):
new_bookmarks = self.get_non_embedded_bookmarks()
for bookmark in new_bookmarks:
self.embed_bookmark(bookmark)
def embed_new_highlights(self, colormap=None):
new_highlights = self.get_non_embedded_highlights()
for highlight in new_highlights:
self.embed_highlight(highlight, colormap)
def embed_new_annotations(self, save=False, colormap=None):
self.embed_new_bookmarks()
self.embed_new_highlights(colormap=colormap)
if save:
self.save_changes()
def save_changes(self):
self.doc.saveIncr()
def get_non_embedded_highlights(self):
candidate_highlights = self.get_highlights()
new_highlights = []
for highlight in candidate_highlights:
highlight_document_pos = highlight.get_begin_document_pos()
pdf_page_highlights = self.get_page_pdf_highlights(highlight_document_pos.page)
found = False
for pdf_highlight in pdf_page_highlights:
if abs(highlight_document_pos.offset_y - pdf_highlight.rect[1]) < 50:
found = True
break
if not found:
new_highlights.append(highlight)
return new_highlights
def get_non_embedded_bookmarks(self):
candidate_bookmarks = self.get_bookmarks()
new_bookmarks = []
for bookmark in candidate_bookmarks:
pdf_page_bookmarks = self.get_page_pdf_bookmarks(bookmark.get_document_position()[0])
found = False
for pdf_bookmark in pdf_page_bookmarks:
if bookmark.description == pdf_bookmark.info['content']:
found = True
break
if not found:
new_bookmarks.append(bookmark)
return new_bookmarks
def get_page_text_and_rects(self, page_number):
page = self.get_page(page_number)
word_data = page.get_text('words')
word_texts = []
word_rects = []
resulting_string = ""
string_rects = []
for i in range(len(word_data)):
word_text = word_data[i][4]
block_no = word_data[i][5]
line_no = word_data[i][6]
if i > 0:
if block_no != word_data[i-1][5]:
word_text = word_text + '\n'
word_texts.append(word_text)
word_rects.append(fitz.Rect(word_data[i][0:4]))
additional_string = word_text
if word_text[-1] != '\n':
additional_string += ' '
resulting_string += additional_string
string_rects.extend([fitz.Rect(word_data[i][0:4])] * len(additional_string))
return resulting_string, string_rects, word_texts, word_rects
def set_page_dimensions(self):
self.page_heights = []
self.page_widths = []
self.cum_page_heights = []
cum_height = 0
for i in range(self.doc.page_count):
page = self.doc.load_page(i)
width, height = page.mediabox_size
self.page_heights.append(height)
self.page_widths.append(width)
self.cum_page_heights.append(cum_height)
cum_height += height
def get_best_selection_rects(self, page_number, text, merge=False):
for i in range(10):
rects = self.get_text_selection_rects(page_number, text, num_errors=i)
if len(rects) > 0:
if i > 0 and merge == True:
rects = merge_rects(rects)
return rects
return None
def get_best_selection(self, page_number, text):
for i in range(10):
res = self.get_text_selection_begin_and_end(page_number, text, num_errors=i)
if res[0][0] != None:
return res
return None
def get_text_selection_rects(self, page_number, text, num_errors=0):
if num_errors == 0:
page = self.get_page(page_number)
rects = page.search_for(text)
return rects
else:
page_text, page_rects, _, _ = self.get_page_text_and_rects(page_number)
match = regex.search('(' + regex.escape(text) + '){e<=' + str(num_errors) +'}', page_text)
if match:
match_begin, match_end = match.span()
rects = page_rects[match_begin + 1: match_end+1]
return list(dict.fromkeys(rects))
else:
return []
def get_text_selection_begin_and_end(self, page_number, text, num_errors=0):
rects = self.get_text_selection_rects(page_number, text, num_errors)
if len(rects) > 0:
begin_x, begin_y = rects[0].top_left
end_x, end_y = rects[-1].bottom_right
return (begin_x, begin_y), (end_x, end_y)
else:
return (None, None), (None, None)
def highlight_selection(self, page_number, selection_begin, selection_end, focus=False):
highlight_string = '{},{},{} {},{},{}'.format(
page_number,
selection_begin[0], selection_begin[1],
page_number,
selection_end[0], selection_end[1])
self.sioyek.keyboard_select(highlight_string, focus=focus)
def highlight_page_text(self, page_number, text, focus=False):
(begin_x, begin_y), (end_x, end_y) = self.get_text_selection_begin_and_end(page_number, text)
if begin_x:
self.highlight_selection(page_number, (begin_x, begin_y), (end_x, end_y), focus=focus)
def highlight_page_text_fault_tolerant(self, page_number, text, focus=False):
best_selection = self.get_best_selection(page_number, text)
if best_selection:
self.highlight_selection(page_number, best_selection[0], best_selection[1], focus=focus)
def get_sentences(self):
res = []
for i in range(self.doc.page_count):
page = self.doc.load_page(i)
sentences = page.get_text().replace('\n', '').split('.')
res.extend([(s, i) for s in sentences])
return res
def get_hash(self):
path_hash_map = self.sioyek.get_path_hash_map()
for path, hash_ in path_hash_map.items():
if os.path.normpath(self.path) == os.path.normpath(path):
self.cached_hash = hash_
return self.cached_hash
def get_bookmarks(self):
doc_hash = self.get_hash()
BOOKMARK_SELECT_QUERY = "select * from bookmarks where document_path='{}'".format(doc_hash)
shared_database = self.sioyek.get_shared_database()
cursor = shared_database.execute(BOOKMARK_SELECT_QUERY)
bookmarks = [Bookmark(self, desc, y_offset) for _, _, desc, y_offset in cursor.fetchall()]
return bookmarks
def get_highlights(self):
doc_hash = self.get_hash()
HIGHLIGHT_SELECT_QUERY = "select * from highlights where document_path='{}'".format(doc_hash)
shared_database = self.sioyek.get_shared_database()
cursor = shared_database.execute(HIGHLIGHT_SELECT_QUERY)
highlights = [Highlight(self, text, highlight_type, (begin_x, begin_y), (end_x, end_y)) for _, _, text, highlight_type, begin_x, begin_y, end_x, end_y in cursor.fetchall()]
return highlights
def close(self):
self.doc.close()