def dark_mode_is_enabled(self): ''' Return bool of whether dark mode is enabled.''' return (get_emacs_var("eaf-browser-dark-mode") == "force" or \ get_emacs_var("eaf-browser-dark-mode") == True or \ (get_emacs_var("eaf-browser-dark-mode") == "follow" and \ get_emacs_var("eaf-emacs-theme-mode") == "dark")) and \ not self.url.startswith("devtools://")
def load_first_file(self): self.buffer_widget.execute_js( '''initPlaylistColor(\"{}\", \"{}\")'''.format( get_emacs_var("eaf-emacs-theme-background-color"), get_emacs_var("eaf-emacs-theme-foreground-color"))) self.buffer_widget.execute_js( '''initPanelColor(\"{}\", \"{}\")'''.format( self.panel_background_color, get_emacs_var("eaf-emacs-theme-foreground-color"))) self.buffer_widget.execute_js('''initPlayOrder(\"{}\")'''.format( get_emacs_var("eaf-music-play-order"))) files = [] if os.path.isdir(self.first_file): files = list( filter(lambda f: os.path.isfile(f), [ os.path.join(dp, f) for dp, dn, filenames in os.walk(self.first_file) for f in filenames ])) elif os.path.isfile(self.first_file): files.append(self.first_file) self.buffer_widget.execute_js('''addFiles({});'''.format( json.dumps(self.pick_music_info(files))))
def try_start_aria2_daemon(self): ''' Try to start aria2 daemon.''' if not is_port_in_use(6800): with open(os.devnull, "w") as null_file: aria2_args = ["aria2c"] aria2_args.append("-d") # daemon aria2_args.append("-c") # continue download aria2_args.append("--auto-file-renaming={}".format( str(get_emacs_var( "eaf-browser-aria2-auto-file-renaming")))) aria2_args.append("-d {}".format( os.path.expanduser( get_emacs_var("eaf-browser-download-path")))) aria2_proxy_host = get_emacs_var( "eaf-browser-aria2-proxy-host") aria2_proxy_port = get_emacs_var( "eaf-browser-aria2-proxy-port") if aria2_proxy_host != "" and aria2_proxy_port != "": aria2_args.append("--all-proxy") aria2_args.append("http://{0}:{1}".format( aria2_proxy_host, aria2_proxy_port)) aria2_args.append("--enable-rpc") aria2_args.append("--rpc-listen-all") subprocess.Popen(aria2_args, stdout=null_file)
def take_photo(self): if os.path.exists(os.path.expanduser(get_emacs_var("eaf-camera-save-path"))): location = get_emacs_var("eaf-camera-save-path") else: location = "~/Downloads" result = self.buffer_widget.take_photo(location) if result: message_to_emacs("Captured Photo at " + location)
def __init__(self, buffer_id, url, arguments): Buffer.__init__(self, buffer_id, url, arguments, False) self.background_color = QColor(get_emacs_var("eaf-emacs-theme-background-color")) self.add_widget(FileTransferWidget(url, get_emacs_var("eaf-emacs-theme-background-color"), get_emacs_var("eaf-emacs-theme-foreground-color")))
def toggle_adblocker(self): ''' Change adblocker status.''' if get_emacs_var("eaf-browser-enable-adblocker"): set_emacs_var("eaf-browser-enable-adblocker", False) self.buffer_widget.remove_css('adblocker', True) message_to_emacs("Successfully disabled adblocker!") elif not get_emacs_var("eaf-browser-enable-adblocker"): set_emacs_var("eaf-browser-enable-adblocker", True) self.load_adblocker() message_to_emacs("Successfully enabled adblocker!")
def __init__(self, args): global emacs_width, emacs_height, proxy_string # Parse init arguments. (emacs_width, emacs_height, emacs_server_port) = args emacs_width = int(emacs_width) emacs_height = int(emacs_height) # Init variables. self.buffer_dict = {} self.view_dict = {} # Init EPC client port. init_epc_client(int(emacs_server_port)) # Build EPC server. self.server = ThreadingEPCServer(('localhost', 0), log_traceback=True) self.server.logger.setLevel(logging.DEBUG) self.server.allow_reuse_address = True eaf_config_dir = get_emacs_config_dir() 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() # Pass epc port and webengine codec information to Emacs when first start EAF. eval_in_emacs('eaf--first-start', [ self.server.server_address[1], self.webengine_include_private_codec() ]) # Set Network proxy. proxy_host = get_emacs_var("eaf-proxy-host") proxy_port = get_emacs_var("eaf-proxy-port") proxy_type = get_emacs_var("eaf-proxy-type") self.proxy = (proxy_type, proxy_host, proxy_port) self.is_proxy = False if proxy_type != "" and proxy_host != "" and proxy_port != "": self.enable_proxy()
def update_play_status(self, status=None): if status == "playing": icon = 'pause-circle' elif status == "paused": icon = 'play-circle' elif (get_emacs_var("eaf-netease-cloud-music-play-status") == "") or (get_emacs_var("eaf-netease-cloud-music-play-status") == "paused"): icon = 'play-circle' else: icon = 'pause-circle' self.buffer_widget.execute_js('''setPlayIconStatus(\"{}\")'''.format(icon))
def set_playlist(self, playlist=None): if playlist: self.buffer_widget.execute_js('''setPlaylist({})'''.format(playlist)) else: if get_emacs_var("eaf-netease-cloud-music-playlist-id") == 0: playlist_var = 'eaf-netease-cloud-music-local-playlist+list' else: playlist_var = 'eaf-netease-cloud-music-playlists-songs+list' self.buffer_widget.execute_js('''setPlaylist({})'''.format( get_emacs_var(playlist_var)))
def open_terminal_page(self): theme = "dark" if self.dark_mode_is_enabled() else "light" with request.urlopen(self.index_file) as f: html = f.read().decode("utf-8").replace("%1", str(self.port))\ .replace("%2", self.http_url)\ .replace("%3", theme)\ .replace("%4", str(get_emacs_var("eaf-terminal-font-size")))\ .replace("%5", self.current_directory)\ .replace("%6", get_emacs_var("eaf-terminal-font-family")) self.buffer_widget.setHtml(html)
def update_progress(self, progress): ''' Update the Progress Bar.''' self.progressbar_progress = progress # We need load dark mode js always, otherwise will white flash when loading page. if self.is_dark_mode_enabled: self.buffer_widget.load_dark_mode_js() self.buffer_widget.enable_dark_mode() if progress < 100: # Update progress. self.caret_js_ready = False self.update() elif progress == 100: if self.is_loading: self.is_loading = False self.buffer_widget.load_marker_file() cursor_foreground_color = "" cursor_background_color = "" self.caret_browsing_js = self.buffer_widget.caret_browsing_js_raw.replace( "%1", cursor_foreground_color).replace("%2", cursor_background_color) self.buffer_widget.eval_js(self.caret_browsing_js) self.caret_js_ready = True if self.dark_mode_is_enabled(): if get_emacs_var("eaf-browser-dark-mode") == "follow": cursor_foreground_color = self.caret_background_color.name( ) cursor_background_color = self.caret_foreground_color.name( ) else: cursor_foreground_color = "#FFF" cursor_background_color = "#000" else: if get_emacs_var("eaf-browser-dark-mode") == "follow": cursor_foreground_color = self.caret_background_color.name( ) cursor_background_color = self.caret_foreground_color.name( ) else: cursor_foreground_color = "#000" cursor_background_color = "#FFF" self.after_page_load_hook() # Run after page load hook
def load_first_file(self): self.buffer_widget.execute_js( '''initProcesslistColor(\"{}\", \"{}\")'''.format( get_emacs_var("eaf-emacs-theme-background-color"), get_emacs_var("eaf-emacs-theme-foreground-color"))) self.buffer_widget.execute_js( '''initPanelColor(\"{}\", \"{}\")'''.format( self.panel_background_color, get_emacs_var("eaf-emacs-theme-foreground-color"))) self.update_process_info() self.timer = QTimer(self) self.timer.timeout.connect(self.update_process_info) self.timer.start(1000)
def __init__(self, buffer_id, url, arguments): BrowserBuffer.__init__(self, buffer_id, url, arguments, False) self.index_file_dir = os.path.join(os.path.dirname(__file__), "dist") self.index_file = os.path.join(self.index_file_dir, "index.html") self.url = url self.first_file = arguments self.panel_background_color = QColor( get_emacs_var("eaf-emacs-theme-background-color")).darker( 110).name() self.buffer_widget.loadFinished.connect(self.load_first_file) with open(self.index_file, "r") as f: html = self.convert_index_html(f.read(), self.index_file_dir) self.buffer_widget.setHtml(html, QUrl("file://")) for (python_method_name, js_method_name) in [("scroll_up", "scrollUp"), ("scroll_down", "scrollDown"), ("scroll_up_page", "scrollUpPage"), ("scroll_down_page", "scrollDownPage"), ("scroll_to_begin", "scrollToBegin"), ("scroll_to_bottom", "scrollToBottom")]: self.build_js_bridge_method(python_method_name, js_method_name)
def init_app(self): self.buffer_widget.execute_js('initColor(\"{}\", \"{}\")'.format( get_emacs_var("eaf-emacs-theme-background-color"), get_emacs_var("eaf-emacs-theme-foreground-color") )) self.update_user_info() self.refresh_user_playlist() self.update_playlist_style(True) self.set_repeat_mode() self.set_panel_song() self.update_play_status() # Init eval_in_emacs('''eaf--netease-cloud-music-init''', []) self.set_playlist() eval_in_emacs('''eaf--netease-cloud-music--update-song-style''', [])
def refresh_user_playlist(self, playlists=None): '''Only refresh the value.''' if playlists: self.buffer_widget.execute_js('''setUserPlaylists({})'''.format(playlists)) else: self.buffer_widget.execute_js('''setUserPlaylists({})'''.format( get_emacs_var("eaf-netease-cloud-music-user-playlists+list")))
def save_page_password(self): ''' Record form data.''' if get_emacs_var("eaf-browser-enable-autofill"): self.add_password_entry() else: message_to_emacs( "Password autofill is not enabled! Enable with `C-t` (default binding)" )
def __init__(self, buffer_id, url, arguments): Buffer.__init__(self, buffer_id, url, arguments, False) arguments_dict = json.loads(arguments) self.kernel = arguments_dict["kernel"] font_size = get_emacs_var("eaf-jupyter-font-size") font_family = get_emacs_var("eaf-jupyter-font-family") self.add_widget( EafJupyterWidget(self.kernel, font_size=font_size, font_family=font_family)) QTimer.singleShot(500, self.focus_widget) self.build_all_methods(self.buffer_widget)
def __init__(self, callback_tag, fetch_marker_callback): QThread.__init__(self) self.callback_tag = callback_tag self.running_flag = True self.fetch_marker_callback = fetch_marker_callback self.marker_quit_keys = get_emacs_var("eaf-marker-quit-keys") or "" self.markers = self.fetch_marker_callback()
def get_save_path(self, extension_name): if self.url.strip() == "": return os.path.join( os.path.expanduser(get_emacs_var("eaf-mindmap-save-path")), self.get_root_node_topic().replace(" ", "_") + time.strftime( "_%Y%m%d_%H%M%S", time.localtime(int(time.time()))) + "." + extension_name) else: return os.path.splitext(self.url)[0] + "." + extension_name
def update_playlist_style(self, init=False, playlist_id=None): if init: func_string = '''changePlaylistStyle({}, true)''' else: func_string = '''changePlaylistStyle({})''' if playlist_id: self.buffer_widget.execute_js(func_string.format(playlist_id)) else: self.buffer_widget.execute_js(func_string.format( get_emacs_var("eaf-netease-cloud-music-playlist-id")))
def record_close_page(self, url): ''' Record closing pages.''' self.page_closed = True if get_emacs_var( "eaf-browser-remember-history" ) and self.arguments != "temp_html_file" and url != "about:blank": touch(self.history_close_file_path) with open(self.history_close_file_path, "r") as f: close_urls = f.readlines() close_urls.append("{0}\n".format(url)) open(self.history_close_file_path, "w").writelines(close_urls)
def translate_page(self): import locale system_language = locale.getdefaultlocale()[0].replace("_", "-") translate_language = get_emacs_var("eaf-browser-translate-language") language = system_language if translate_language == "" else translate_language url = urllib.parse.quote(self.buffer_widget.url().toString(), safe='') open_url_in_new_tab( "https://translate.google.com/translate?hl=en&sl=auto&tl={}&u={}". format(language, url)) message_to_emacs("Translating page...")
def __init__(self, kernel, *args, **kwargs): bg_color = get_emacs_var("eaf-emacs-theme-background-color") fg_color = get_emacs_var("eaf-emacs-theme-foreground-color") dark_mode = (get_emacs_var("eaf-jupyter-dark-mode") == "force" or \ get_emacs_var("eaf-jupyter-dark-mode") == True or \ (get_emacs_var("eaf-jupyter-dark-mode") == "follow" and get_emacs_var("eaf-emacs-theme-mode") == "dark")) self._init_style(bg_color, fg_color, dark_mode) self.scrollbar_visibility = False super(EafJupyterWidget, self).__init__(*args, **kwargs) kernel_manager = QtKernelManager(kernel_name=kernel) kernel_manager.start_kernel() kernel_client = kernel_manager.client() kernel_client.start_channels() self.kernel_manager = kernel_manager self.kernel_client = kernel_client self._control.setStyleSheet("border: none;") self._page_control.setStyleSheet("border: none;") self._kill_ring = EafKillRing(self._control)
def init_path(self): path = os.path.expanduser(self.url) search_path = Path(path) file_infos = [] for p in search_path.glob("*"): if not p.name.startswith("."): file_type = "file" if p.is_dir(): file_type = "directory" elif p.is_symlink(): file_type = "symlink" file_info = { "path": str(p.absolute()), "name": p.name, "type": file_type } file_infos.append(file_info) file_infos.sort(key=cmp_to_key(self.file_compare)) self.buffer_widget.execute_js('''addPath(\"{}\");'''.format(path)) self.buffer_widget.execute_js('''addFiles({});'''.format( json.dumps(file_infos))) self.buffer_widget.execute_js( '''initColors(\"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\", \"{}\")''' .format( get_emacs_var("eaf-emacs-theme-background-color"), get_emacs_var("eaf-emacs-theme-foreground-color"), self.arguments["header-color"], get_emacs_var("eaf-emacs-theme-foreground-color"), self.arguments["directory-color"], self.arguments["symlink-color"], self.arguments["select-color"], ))
def toggle_password_autofill(self): ''' Toggle Autofill status for password data''' if not get_emacs_var("eaf-browser-enable-autofill"): set_emacs_var("eaf-browser-enable-autofill", True) self.pw_autofill_id = self.pw_autofill_gen_id(0) message_to_emacs("Successfully enabled autofill!") else: self.pw_autofill_id = self.pw_autofill_gen_id(self.pw_autofill_id) if self.pw_autofill_id == 0: set_emacs_var("eaf-browser-enable-autofill", False) message_to_emacs("Successfully disabled password autofill!") else: message_to_emacs("Successfully changed password autofill id!")
def __init__(self, buffer_id, url, arguments): BrowserBuffer.__init__(self, buffer_id, url, arguments, False) self.url = url self.preview_file = tempfile.mkstemp(prefix='eaf-', suffix='.html', text=True)[1] self.render_js = os.path.join(os.path.dirname(__file__), "render.js") self.server_port = get_free_port() self.dark_mode = "false" if (get_emacs_var("eaf-markdown-dark-mode") == "force" or \ get_emacs_var("eaf-markdown-dark-mode") == True or \ (get_emacs_var("eaf-markdown-dark-mode") == "follow" and get_emacs_var("eaf-emacs-theme-mode") == "dark")): self.dark_mode = "true" self.draw_progressbar = True self.run_render_server() self.render() self.file_watcher = QFileSystemWatcher() self.file_watcher.fileChanged.connect(self.on_file_changed) self.file_watcher.addPath(url)
def __init__(self, buffer_id, url, arguments): BrowserBuffer.__init__(self, buffer_id, url, arguments, False) self.url = url index_file = os.path.join(os.path.dirname(__file__), "index.html") self.buffer_widget.setUrl(QUrl.fromLocalFile(index_file)) self.cut_node_id = None edit_mode = "true" if get_emacs_var( "eaf-mindmap-edit-mode") else "false" for method_name in [ "add_sub_node", "add_brother_node", "add_middle_node" ]: self.build_js_method(method_name, True, js_kwargs={"inline": edit_mode}) for method_name in [ "remove_node", "remove_middle_node", "update_node_topic_inline" ]: self.build_js_method(method_name, True) for method_name in [ "zoom_in", "zoom_out", "zoom_reset", "select_up_node", "select_down_node", "select_left_node", "select_right_node", "toggle_node", "toggle_node_selection", "save_screenshot" ]: self.build_js_method(method_name) for method_name in [ "zoom_in", "zoom_out", "zoom_reset", "remove_node", "remove_middle_node", "add_middle_node", "refresh_page", "select_up_node", "select_down_node", "select_left_node", "select_right_node", "toggle_node", "toggle_node_selection", "save_screenshot" ]: self.build_insert_or_do(method_name) self.build_all_methods(self) self.buffer_widget.loadFinished.connect(lambda _: self.initialize())
def _import_chrome_history(self): dbpath = os.path.expanduser( get_emacs_var("eaf-browser-chrome-history-file")) if not os.path.exists(dbpath): message_to_emacs( "The chrome history file: '{}' not exist, please check your setting." .format(dbpath)) return message_to_emacs("Importing from {}...".format(dbpath)) conn = sqlite3.connect(dbpath) # Keep lastest entry in dict by last_visit_time asc order. sql = 'select title, url from urls order by last_visit_time asc' # May fetch many by many not fetch all, # but this should called only once, so not important now. try: chrome_histories = conn.execute(sql).fetchall() except sqlite3.OperationalError as e: if e.args[0] == 'database is locked': message_to_emacs( "The chrome history file is locked, please close your chrome app first." ) else: message_to_emacs( "Failed to read chrome history entries: {}.".format(e)) return histories = dict( chrome_histories) # Drop duplications with same title. total = len(histories) for i, (title, url) in enumerate(histories.items(), 1): self._record_history(title, url) message_to_emacs("Importing {} / {} ...".format(i, total)) message_to_emacs( "{} chrome history entries imported.".format(total))
def play_or_pause(self): if get_emacs_var("eaf-netease-cloud-music-play-status") == "": message_to_emacs("You've never started to play a song.") return eval_in_emacs("netease-cloud-music-pause-or-continue", [])
def set_repeat_mode(self, mode=None): if mode: self.buffer_widget.execute_js('''setRepeatMode(\"{}\")'''.format(mode)) else: self.buffer_widget.execute_js('''setRepeatMode(\"{}\")'''.format( get_emacs_var("eaf-netease-cloud-music-repeat-mode")))