update eaf package

This commit is contained in:
2021-01-30 14:52:51 +01:00
parent 84eb4929ee
commit 5207af83cb
4981 changed files with 11795 additions and 761570 deletions

View File

@@ -23,46 +23,66 @@
# QtWebEngine will throw error "ImportError: QtWebEngineWidgets must be imported before a QCoreApplication instance is created"
# So we import browser module before start Qt application instance to avoid this error, but we never use this module.
from app.browser.buffer import AppBuffer as NeverUsed # noqa
from sys import version_info
from PyQt5 import QtWidgets
from PyQt5.QtCore import QLibraryInfo, QTimer
from PyQt5.QtNetwork import QNetworkProxy
from PyQt5.QtWidgets import QApplication
from core.utils import PostGui, string_to_base64
from core.view import View
from dbus.mainloop.glib import DBusGMainLoop
import dbus
import dbus.service
from epc.server import ThreadingEPCServer
from sys import version_info
import importlib
import json
import logging
import os
import platform
import socket
import subprocess
import threading
EAF_DBUS_NAME = "com.lazycat.eaf"
EAF_OBJECT_NAME = "/com/lazycat/eaf"
class EAF(dbus.service.Object):
class EAF(object):
def __init__(self, args):
global emacs_width, emacs_height, eaf_config_dir, proxy_string
dbus.service.Object.__init__(
self,
dbus.service.BusName(EAF_DBUS_NAME, bus=dbus.SessionBus()),
EAF_OBJECT_NAME)
(emacs_width, emacs_height, proxy_host, proxy_port, proxy_type, config_dir, var_dict_string) = args
# Parse init arguments.
(emacs_width, emacs_height, proxy_host, proxy_port, proxy_type, config_dir, emacs_server_port, var_dict_string) = args
emacs_width = int(emacs_width)
emacs_height = int(emacs_height)
eaf_config_dir = os.path.expanduser(config_dir)
eaf_config_dir = os.path.join(os.path.expanduser(config_dir), '')
# Init variables.
self.buffer_dict = {}
self.view_dict = {}
self.emacs_var_dict = {}
self.session_file = os.path.join(eaf_config_dir, "session.json")
# Update Emacs var dictionary.
self.update_emacs_var_dict(var_dict_string)
self.first_start(self.webengine_include_private_codec())
# Build EPC server.
self.server = ThreadingEPCServer(('localhost', 0), log_traceback=True)
self.server.logger.setLevel(logging.DEBUG)
self.server.allow_reuse_address = True
self.session_file = os.path.join(eaf_config_dir, "session.json")
if not os.path.exists(eaf_config_dir):
os.makedirs(eaf_config_dir);
ch = logging.FileHandler(filename=os.path.join(eaf_config_dir, 'epc_log.txt'), mode='w')
ch.setLevel(logging.DEBUG)
self.server.logger.addHandler(ch)
self.server.register_instance(self) # register instance functions let elisp side call
# Start EPC server with sub-thread, avoid block Qt main loop.
self.server_thread = threading.Thread(target=self.server.serve_forever)
self.server_thread.start()
# Build emacs server connect, used to send message from Python to elisp side.
self.emacs_server_connect = self.build_emacs_server_connect(int(emacs_server_port))
# Pass epc port and webengine codec information to Emacs when first start EAF.
self.first_start(self.server.server_address[1], self.webengine_include_private_codec())
# Set Network proxy.
if proxy_host != "" and proxy_port != "":
@@ -78,6 +98,11 @@ class EAF(dbus.service.Object):
proxy.setPort(int(proxy_port))
QNetworkProxy.setApplicationProxy(proxy)
def build_emacs_server_connect(self, port):
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect(('127.0.0.1', port))
return conn
def get_command_result(self, command):
''' Execute the command and return the result. '''
if version_info >= (3,7):
@@ -87,10 +112,12 @@ class EAF(dbus.service.Object):
def webengine_include_private_codec(self):
''' Return bool of whether the QtWebEngineProcess include private codec. '''
if platform.system() == "Windows":
return "False"
path = os.path.join(QLibraryInfo.location(QLibraryInfo.LibraryExecutablesPath), "QtWebEngineProcess")
return self.get_command_result("ldd {} | grep libavformat".format(path)) != ""
@dbus.service.method(EAF_DBUS_NAME, in_signature="s", out_signature="")
@PostGui()
def update_emacs_var_dict(self, var_dict_string):
''' Update Python side emacs_var_dict.(Fix issue #206) '''
self.emacs_var_dict = json.loads(var_dict_string)
@@ -98,14 +125,12 @@ class EAF(dbus.service.Object):
for buffer in list(self.buffer_dict.values()):
buffer.emacs_var_dict = self.emacs_var_dict
@dbus.service.method(EAF_DBUS_NAME, in_signature="ssss", out_signature="s")
@PostGui()
def new_buffer(self, buffer_id, url, app_name, arguments):
''' Create new buffer. '''
# NOTE: We need use function str convert dbus.String to String,
# otherwise some library will throw error, such as fitz library.
return self.create_app(buffer_id, str(url), "app.{0}.buffer".format(str(app_name)), str(arguments))
self.create_app(buffer_id, str(url), "app.{0}.buffer".format(str(app_name)), str(arguments))
@dbus.service.method(EAF_DBUS_NAME, in_signature="sss", out_signature="")
@PostGui()
def update_buffer_with_url(self, module_path, buffer_url, update_data):
''' Update buffer with url '''
for buffer in list(self.buffer_dict.values()):
@@ -113,7 +138,7 @@ class EAF(dbus.service.Object):
buffer.update_with_data(update_data)
break
@dbus.service.method(EAF_DBUS_NAME, in_signature="sss", out_signature="")
@PostGui()
def scroll_other_buffer(self, view_info, scroll_direction, scroll_type):
''' Scroll to other buffer '''
(buffer_id, _, _, _, _) = view_info.split(":")
@@ -177,6 +202,7 @@ class EAF(dbus.service.Object):
app_buffer.update_buffer_details.connect(self.update_buffer_details)
app_buffer.translate_text.connect(self.translate_text)
app_buffer.open_url_in_new_tab.connect(self.open_url_in_new_tab)
app_buffer.duplicate_page_in_new_tab.connect(self.duplicate_page_in_new_tab)
app_buffer.open_url_in_background_tab.connect(self.open_url_in_background_tab)
app_buffer.goto_left_tab.connect(self.goto_left_tab)
app_buffer.goto_right_tab.connect(self.goto_right_tab)
@@ -198,10 +224,22 @@ class EAF(dbus.service.Object):
# Handle get_focus_text signal.
if getattr(app_buffer, "get_focus_text", False) and getattr(app_buffer.get_focus_text, "connect", False):
app_buffer.get_focus_text.connect(self.edit_focus_text)
app_buffer.get_focus_text.connect(self.atomic_edit)
if getattr(app_buffer.buffer_widget, "get_focus_text", False) and getattr(app_buffer.buffer_widget.get_focus_text, "connect", False):
app_buffer.buffer_widget.get_focus_text.connect(self.edit_focus_text)
app_buffer.buffer_widget.get_focus_text.connect(self.atomic_edit)
# Handle get_sub_node_id signal.
if getattr(app_buffer, "get_sub_node_id", False) and getattr(app_buffer.get_sub_node_id, "connect", False):
app_buffer.get_sub_node_id.connect(self.add_multiple_sub_nodes)
# Handle get_brother_node_id signal.
if getattr(app_buffer, "get_brother_node_id", False) and getattr(app_buffer.get_brother_node_id, "connect", False):
app_buffer.get_brother_node_id.connect(self.add_multiple_brother_nodes)
# Handle get_middle_node_id signal.
if getattr(app_buffer, "get_middle_node_id", False) and getattr(app_buffer.get_middle_node_id, "connect", False):
app_buffer.get_middle_node_id.connect(self.add_multiple_middle_nodes)
# Handle trigger_focus_event signal.
if getattr(app_buffer.buffer_widget, "trigger_focus_event", False) and getattr(app_buffer.buffer_widget.trigger_focus_event, "connect", False):
@@ -242,11 +280,14 @@ class EAF(dbus.service.Object):
return app_buffer
@dbus.service.method(EAF_DBUS_NAME, in_signature="s", out_signature="")
@PostGui()
def update_views(self, args):
''' Update views.'''
view_infos = args.split(",")
# Show cursor anyway.
QtWidgets.qApp.restoreOverrideCursor()
# Do something if buffer's all view hide after update_views operation.
old_view_buffer_ids = list(set(map(lambda v: v.buffer_id, self.view_dict.values())))
new_view_buffer_ids = list(set(map(lambda v: v.split(":")[0], view_infos)))
@@ -265,7 +306,7 @@ class EAF(dbus.service.Object):
self.view_dict[key].destroy_view()
self.view_dict.pop(key, None)
# Create new view and udpate in view dict.
# Create new view and update in view dict.
if view_infos != ['']:
for view_info in view_infos:
if view_info not in self.view_dict:
@@ -302,7 +343,7 @@ class EAF(dbus.service.Object):
# Send resize signal to buffer.
buffer.resize_view()
@dbus.service.method(EAF_DBUS_NAME, in_signature="", out_signature="")
@PostGui()
def kill_emacs(self):
''' Kill all buffurs from buffer dict.'''
tmp_buffer_dict = {}
@@ -312,7 +353,7 @@ class EAF(dbus.service.Object):
for buffer_id in tmp_buffer_dict:
self.kill_buffer(buffer_id)
@dbus.service.method(EAF_DBUS_NAME, in_signature="s", out_signature="")
@PostGui()
def kill_buffer(self, buffer_id):
''' Kill all view based on buffer_id and clean buffer from buffer dict.'''
# Kill all view base on buffer_id.
@@ -329,7 +370,7 @@ class EAF(dbus.service.Object):
self.buffer_dict[buffer_id].destroy_buffer()
self.buffer_dict.pop(buffer_id, None)
@dbus.service.method(EAF_DBUS_NAME, in_signature="sss", out_signature="")
@PostGui()
def execute_function(self, buffer_id, function_name, event_string):
''' Execute function and do not return anything. '''
if buffer_id in self.buffer_dict:
@@ -342,7 +383,6 @@ class EAF(dbus.service.Object):
traceback.print_exc()
self.message_to_emacs("Cannot execute function: " + function_name + " (" + buffer_id + ")")
@dbus.service.method(EAF_DBUS_NAME, in_signature="ss", out_signature="s")
def call_function(self, buffer_id, function_name):
''' Call function and return the result. '''
if buffer_id in self.buffer_dict:
@@ -354,132 +394,159 @@ class EAF(dbus.service.Object):
self.message_to_emacs("Cannot call function: " + function_name)
return ""
@dbus.service.method(EAF_DBUS_NAME, in_signature="sss", out_signature="s")
def call_function_with_args(self, buffer_id, function_name, args_string):
def call_function_with_args(self, buffer_id, function_name, *args, **kwargs):
''' Call function with arguments and return the result. '''
if buffer_id in self.buffer_dict:
try:
return str(self.buffer_dict[buffer_id].call_function_with_args(function_name, args_string))
return str(self.buffer_dict[buffer_id].call_function_with_args(function_name, *args, **kwargs))
except AttributeError:
import traceback
traceback.print_exc()
self.message_to_emacs("Cannot call function: " + function_name)
return ""
@dbus.service.method(EAF_DBUS_NAME, in_signature="s", out_signature="")
@PostGui()
def action_quit(self, buffer_id):
''' Execute action_quit() for specified buffer.'''
if buffer_id in self.buffer_dict:
self.buffer_dict[buffer_id].action_quit()
@dbus.service.method(EAF_DBUS_NAME, in_signature="ss", out_signature="")
@PostGui()
def send_key(self, buffer_id, event_string):
''' Send event to buffer when found match buffer.'''
if buffer_id in self.buffer_dict:
self.buffer_dict[buffer_id].fake_key_event(event_string)
@dbus.service.method(EAF_DBUS_NAME, in_signature="ss", out_signature="")
@PostGui()
def send_key_sequence(self, buffer_id, event_string):
''' Send event to buffer when found match buffer.'''
if buffer_id in self.buffer_dict:
self.buffer_dict[buffer_id].fake_key_sequence(event_string)
@dbus.service.method(EAF_DBUS_NAME, in_signature="sss", out_signature="")
def handle_input_message(self, buffer_id, callback_type, callback_result):
@PostGui()
def handle_input_response(self, buffer_id, callback_tag, callback_result):
''' Handle input message for specified buffer.'''
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
buffer.handle_input_message(callback_type, callback_result)
buffer.handle_input_response(callback_tag, callback_result)
@dbus.service.method(EAF_DBUS_NAME, in_signature="ss", out_signature="")
def cancel_input_message(self, buffer_id, callback_type):
@PostGui()
def cancel_input_response(self, buffer_id, callback_tag):
''' Cancel input message for specified buffer.'''
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
buffer.cancel_input_message(callback_type)
buffer.cancel_input_response(callback_tag)
@dbus.service.method(EAF_DBUS_NAME, in_signature="ss", out_signature="")
@PostGui()
def update_focus_text(self, buffer_id, new_text):
''' Update focus text for specified buffer.'''
import base64
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
buffer.set_focus_text(new_text)
buffer.set_focus_text(base64.b64decode(new_text).decode("utf-8"))
@PostGui()
def update_multiple_sub_nodes(self, buffer_id, new_text):
''' Update multiplt sub nodes.'''
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
for line in str(new_text).split("\n"):
buffer.add_texted_sub_node(line)
@PostGui()
def update_multiple_brother_nodes(self, buffer_id, new_text):
''' Update multiplt brother nodes.'''
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
for line in str(new_text).split("\n"):
buffer.add_texted_brother_node(line)
@PostGui()
def update_multiple_middle_nodes(self, buffer_id, new_text):
''' Update multiplt middle nodes.'''
for buffer in list(self.buffer_dict.values()):
if buffer.buffer_id == buffer_id:
for line in str(new_text).split("\n"):
buffer.add_texted_middle_node(line)
def eval_in_emacs(self, method_name, args_list):
code = "(" + str(method_name)
for arg in args_list:
arg = str(arg)
if len(arg) > 0 and arg[0] == "'":
code += " {}".format(arg)
else:
code += " \"{}\"".format(arg)
code += ")"
self.emacs_server_connect.send(str.encode(code))
def add_multiple_sub_nodes(self, buffer_id):
self.eval_in_emacs('eaf--add-multiple-sub-nodes', [buffer_id])
def add_multiple_brother_nodes(self, buffer_id):
self.eval_in_emacs('eaf--add-multiple-brother-nodes', [buffer_id])
def add_multiple_middle_nodes(self, buffer_id):
self.eval_in_emacs('eaf--add-multiple-middle-nodes', [buffer_id])
@dbus.service.signal(EAF_DBUS_NAME)
def focus_emacs_buffer(self, message):
pass
self.eval_in_emacs('eaf-focus-buffer', [message])
@dbus.service.signal(EAF_DBUS_NAME)
def first_start(self, webengine_include_private_codec):
pass
def first_start(self, port, webengine_include_private_codec):
self.eval_in_emacs('eaf--first-start', [port, webengine_include_private_codec])
@dbus.service.signal(EAF_DBUS_NAME)
def update_buffer_details(self, buffer_id, title, url):
pass
self.eval_in_emacs('eaf--update-buffer-details', [buffer_id, title, url])
@dbus.service.signal(EAF_DBUS_NAME)
def open_url_in_new_tab(self, url):
pass
self.eval_in_emacs('eaf-open-browser', [url])
def duplicate_page_in_new_tab(self, url):
self.eval_in_emacs('eaf-browser--duplicate-page-in-new-tab', [url])
@dbus.service.signal(EAF_DBUS_NAME)
def open_dev_tools_page(self):
pass
self.eval_in_emacs('eaf-open-dev-tool-page', [])
@dbus.service.signal(EAF_DBUS_NAME)
def open_url_in_background_tab(self, url):
pass
self.eval_in_emacs('eaf-open-browser-in-background', [url])
@dbus.service.signal(EAF_DBUS_NAME)
def goto_left_tab(self):
pass
self.eval_in_emacs('eaf-goto-left-tab', [])
@dbus.service.signal(EAF_DBUS_NAME)
def goto_right_tab(self):
pass
self.eval_in_emacs('eaf-goto-right-tab', [])
@dbus.service.signal(EAF_DBUS_NAME)
def translate_text(self, text):
pass
self.eval_in_emacs('eaf-translate-text', [text])
@dbus.service.signal(EAF_DBUS_NAME)
def input_message(self, buffer_id, message, callback_type, input_type, input_content):
pass
def input_message(self, buffer_id, message, callback_tag, input_type, input_content):
self.eval_in_emacs('eaf--input-message', [buffer_id, message, callback_tag, input_type, input_content])
@dbus.service.signal(EAF_DBUS_NAME)
def create_new_browser_buffer(self, buffer_id):
pass
self.eval_in_emacs('eaf--create-new-browser-buffer', [buffer_id])
@dbus.service.signal(EAF_DBUS_NAME)
def request_kill_buffer(self, buffer_id):
pass
self.eval_in_emacs('eaf-request-kill-buffer', [buffer_id])
@dbus.service.signal(EAF_DBUS_NAME)
def message_to_emacs(self, message):
pass
self.eval_in_emacs('eaf--show-message', [string_to_base64(message)])
@dbus.service.signal(EAF_DBUS_NAME)
def set_emacs_var(self, var_name, var_value):
pass
def set_emacs_var(self, var_name, var_value, eaf_specific):
self.eval_in_emacs('eaf--set-emacs-var', [var_name, var_value, eaf_specific])
@dbus.service.signal(EAF_DBUS_NAME)
def eval_in_emacs(self, elisp_code_string):
pass
def atomic_edit(self, buffer_id, focus_text):
self.eval_in_emacs('eaf--atomic-edit', [buffer_id, string_to_base64(focus_text)])
@dbus.service.signal(EAF_DBUS_NAME)
def edit_focus_text(self, buffer_id, focus_text):
pass
@dbus.service.signal(EAF_DBUS_NAME)
def export_org_json(self, org_json_content, org_file_path):
pass
self.eval_in_emacs('eaf--export-org-json', [org_json_content, org_file_path])
@dbus.service.signal(EAF_DBUS_NAME)
def enter_fullscreen_request(self):
pass
self.eval_in_emacs('eaf--enter-fullscreen-request', [])
@dbus.service.signal(EAF_DBUS_NAME)
def exit_fullscreen_request(self):
pass
self.eval_in_emacs('eaf--exit_fullscreen_request', [])
def open_dev_tools_tab(self, web_page):
''' Open dev-tools tab'''
@@ -552,20 +619,14 @@ if __name__ == "__main__":
proxy_string = ""
DBusGMainLoop(set_as_default=True) # WARING: only use once in one process
emacs_width = emacs_height = 0
eaf_config_dir = ""
bus = dbus.SessionBus()
if bus.request_name(EAF_DBUS_NAME) != dbus.bus.REQUEST_NAME_REPLY_PRIMARY_OWNER:
print("EAF process is already running.")
else:
emacs_width = emacs_height = 0
eaf_config_dir = ""
app = QApplication(sys.argv + ["--disable-web-security"])
app = QApplication(sys.argv + ["--disable-web-security"])
eaf = EAF(sys.argv[1:])
eaf = EAF(sys.argv[1:])
print("EAF process starting...")
print("EAF process starting...")
signal.signal(signal.SIGINT, signal.SIG_DFL)
sys.exit(app.exec_())
signal.signal(signal.SIGINT, signal.SIG_DFL)
sys.exit(app.exec_())