Clean up deprecated code and fix multiple issues
- Remove deprecated markdown_preview plugin and re-wrote - Renamed alt_provider.py under words completer - Fix words completion provider logic and cache handling - Fix container orientations (VERTICAL -> HORIZONTAL) and add Separators - Remove unused Gtk imports from search_replace plugin - Fix event creation parameter order in source_file.py - Fix typo in source_view.py (_load_pretify_json -> _load_prettify_json) - Refactor webkit_ui with new load methods and enhanced settings
This commit is contained in:
@@ -32,8 +32,23 @@ class Provider(GtkSource.CompletionWords):
|
|||||||
return 'Words Completion'
|
return 'Words Completion'
|
||||||
|
|
||||||
def do_match(self, context):
|
def do_match(self, context):
|
||||||
|
# Note: If provider is in interactive activation then need to check
|
||||||
|
# view focus as otherwise non focus views start trying to grab it.
|
||||||
|
completion = context.get_property("completion")
|
||||||
|
if not completion.get_view().has_focus(): return
|
||||||
|
|
||||||
word = self.response_cache.get_word(context)
|
word = self.response_cache.get_word(context)
|
||||||
if not word or len(word) < 2: return False
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
iter = self.response_cache.get_iter_correctly(context)
|
||||||
|
iter.backward_char()
|
||||||
|
ch = iter.get_char()
|
||||||
|
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||||
|
# As is it slows down the editor in certain contexts...
|
||||||
|
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||||
|
if not (ch in ('_', '.') or ch.isalnum()):
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def do_get_priority(self):
|
def do_get_priority(self):
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
from core.widgets.code.completion_providers.provider_response_cache_base import ProviderResponseCacheBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderResponseCache(ProviderResponseCacheBase):
|
||||||
|
def __init__(self):
|
||||||
|
super(ProviderResponseCache, self).__init__()
|
||||||
|
|
||||||
|
self.matchers: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
|
...
|
||||||
|
|
||||||
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
|
...
|
||||||
@@ -18,7 +18,7 @@ class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
|||||||
This is a Words Completion Provider.
|
This is a Words Completion Provider.
|
||||||
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
# NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/
|
||||||
"""
|
"""
|
||||||
# __gtype_name__ = 'WordsCompletionProvider'
|
__gtype_name__ = 'WordsCompletionProvider'
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Provider, self).__init__()
|
super(Provider, self).__init__()
|
||||||
@@ -37,6 +37,16 @@ class Provider(GObject.GObject, GtkSource.CompletionProvider):
|
|||||||
|
|
||||||
word = self.response_cache.get_word(context)
|
word = self.response_cache.get_word(context)
|
||||||
if not word or len(word) < 2: return False
|
if not word or len(word) < 2: return False
|
||||||
|
|
||||||
|
iter = self.response_cache.get_iter_correctly(context)
|
||||||
|
iter.backward_char()
|
||||||
|
ch = iter.get_char()
|
||||||
|
# NOTE: Look to re-add or apply supprting logic to use spaces
|
||||||
|
# As is it slows down the editor in certain contexts...
|
||||||
|
# if not (ch in ('_', '.', ' ') or ch.isalnum()):
|
||||||
|
if not (ch in ('_', '.') or ch.isalnum()):
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def do_get_priority(self):
|
def do_get_priority(self):
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ class ProviderResponseCache(ProviderResponseCacheBase):
|
|||||||
self.matchers[buffer] = set()
|
self.matchers[buffer] = set()
|
||||||
|
|
||||||
def load_into_set(self, buffer, new_words):
|
def load_into_set(self, buffer, new_words):
|
||||||
self.matchers[buffer].update(new_words)
|
# self.matchers[buffer].update(new_words)
|
||||||
|
self.matchers[buffer] = new_words
|
||||||
|
|
||||||
def load_as_new_set(self, buffer, data):
|
def load_as_new_set(self, buffer, data):
|
||||||
self.matchers[buffer] = self.get_all_words(data)
|
self.matchers[buffer] = self.get_all_words(data)
|
||||||
|
|||||||
7
plugins/code/markdown_preview/manifest.json
Normal file
7
plugins/code/markdown_preview/manifest.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "Markdown Preview",
|
||||||
|
"author": "ITDominator",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"support": "",
|
||||||
|
"requests": {}
|
||||||
|
}
|
||||||
101
plugins/code/markdown_preview/markdown_preview.py
Normal file
101
plugins/code/markdown_preview/markdown_preview.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
gi.require_version('Gdk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gdk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from core.widgets.webkit.webkit_ui import WebkitUI
|
||||||
|
|
||||||
|
from .mixins.markdown_preview_mixin import MarkdownPreviewMixin
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownPreview(Gtk.Popover, MarkdownPreviewMixin):
|
||||||
|
def __init__(self):
|
||||||
|
super(MarkdownPreview, self).__init__()
|
||||||
|
|
||||||
|
self.can_hide: bool = True
|
||||||
|
self.is_preview_paused: bool = True # True by default b/c started hidden
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
ctx = self.get_style_context()
|
||||||
|
ctx.add_class("markdown-preview")
|
||||||
|
|
||||||
|
self.set_modal(False)
|
||||||
|
self.set_can_focus(False)
|
||||||
|
self.set_transitions_enabled(False)
|
||||||
|
self.set_size_request(480, 720)
|
||||||
|
self.override_background_color(
|
||||||
|
Gtk.StateFlags.NORMAL,
|
||||||
|
Gdk.RGBA(0, 0, 0, 0.0)
|
||||||
|
)
|
||||||
|
self.set_constrain_to(
|
||||||
|
Gtk.PopoverConstraint.WINDOW
|
||||||
|
)
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
self.connect("hide", self._handle_hide)
|
||||||
|
self.connect("show", self._handle_show)
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
box = Gtk.Box()
|
||||||
|
bttn_box = Gtk.ButtonBox()
|
||||||
|
scrolled_win = Gtk.ScrolledWindow()
|
||||||
|
viewport = Gtk.Viewport()
|
||||||
|
self._markdown_view = WebkitUI()
|
||||||
|
|
||||||
|
self.start_stop_bttn = Gtk.ToggleButton()
|
||||||
|
settings_bttn = Gtk.Button()
|
||||||
|
|
||||||
|
self.start_stop_bttn.set_label("gtk-media-pause")
|
||||||
|
self.start_stop_bttn.set_use_stock(True)
|
||||||
|
|
||||||
|
settings_bttn.set_image(
|
||||||
|
Gtk.Image.new_from_stock(
|
||||||
|
"gtk-justify-fill", Gtk.IconSize.BUTTON
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self._markdown_view.set_vexpand(True)
|
||||||
|
box.set_orientation(Gtk.Orientation.VERTICAL)
|
||||||
|
|
||||||
|
self.start_stop_bttn.connect("clicked", self._tggle_preview_updates)
|
||||||
|
settings_bttn.connect("clicked", self._handle_settings)
|
||||||
|
|
||||||
|
bttn_box.pack_end(self.start_stop_bttn, expand = False, fill = False, padding = 1)
|
||||||
|
bttn_box.pack_end(settings_bttn, expand = False, fill = False, padding = 1)
|
||||||
|
viewport.add(self._markdown_view)
|
||||||
|
scrolled_win.add(viewport)
|
||||||
|
box.add(bttn_box)
|
||||||
|
box.add(scrolled_win)
|
||||||
|
self.add(box)
|
||||||
|
|
||||||
|
box.show_all()
|
||||||
|
|
||||||
|
|
||||||
|
def _handle_hide(self, widget):
|
||||||
|
if self.can_hide:
|
||||||
|
self.is_preview_paused = True
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _handle_show(self, widget):
|
||||||
|
self.can_hide = False
|
||||||
|
self.is_preview_paused = self.start_stop_bttn.get_active()
|
||||||
|
|
||||||
|
def _tggle_preview_updates(self, widget):
|
||||||
|
self.is_preview_paused = not self.is_preview_paused
|
||||||
|
|
||||||
|
def _handle_settings(self, widget):
|
||||||
|
...
|
||||||
3
plugins/code/markdown_preview/mixins/__init__.py
Normal file
3
plugins/code/markdown_preview/mixins/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
"""
|
||||||
|
Pligin Module Mixins
|
||||||
|
"""
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from .markdown_template_mixin import MarkdownTemplateMixin
|
||||||
|
|
||||||
|
from .. import markdown
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownPreviewMixin(MarkdownTemplateMixin):
|
||||||
|
def _do_markdown_translate(self, buffer):
|
||||||
|
if self.is_preview_paused: return
|
||||||
|
|
||||||
|
if not self.is_markdown(buffer):
|
||||||
|
data = self.wrap_html_to_body("<h1>Not a Markdown file...</h1>")
|
||||||
|
self._load_html(data)
|
||||||
|
return
|
||||||
|
|
||||||
|
data = self.get_rendered_markdown(buffer)
|
||||||
|
self._load_html(data)
|
||||||
|
|
||||||
|
def _load_html(self, data: str):
|
||||||
|
self._markdown_view.load_html(
|
||||||
|
content = data, base_uri = None
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_rendered_markdown(self, buffer) -> str:
|
||||||
|
start_itr = buffer.get_start_iter()
|
||||||
|
end_itr = buffer.get_end_iter()
|
||||||
|
text = buffer.get_text(start_itr, end_itr, include_hidden_chars = False)
|
||||||
|
html = markdown.markdown(text)
|
||||||
|
|
||||||
|
return self.wrap_html_to_body(html)
|
||||||
|
|
||||||
|
def is_markdown(self, buffer) -> bool:
|
||||||
|
return buffer.get_language() and buffer.get_language().get_id() == "markdown"
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class MarkdownTemplateMixin:
|
class MarkdownTemplateMixin:
|
||||||
def wrap_html_to_body(self, html):
|
def wrap_html_to_body(self, html: str):
|
||||||
return f"""\
|
return f"""\
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" dir="ltr">
|
<html lang="en" dir="ltr">
|
||||||
@@ -17,7 +17,8 @@ class MarkdownTemplateMixin:
|
|||||||
<style media="screen">
|
<style media="screen">
|
||||||
html, body {{
|
html, body {{
|
||||||
display: block;
|
display: block;
|
||||||
background-color: #32383e00;
|
// background-color: #32383e64;
|
||||||
|
background-color: #32383e;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-wrap: wrap;
|
text-wrap: wrap;
|
||||||
}}
|
}}
|
||||||
56
plugins/code/markdown_preview/plugin.py
Normal file
56
plugins/code/markdown_preview/plugin.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
|
|
||||||
|
from plugins.plugin_types import PluginCode
|
||||||
|
|
||||||
|
from .markdown_preview import MarkdownPreview
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
markdown_preview = MarkdownPreview()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(PluginCode):
|
||||||
|
def __init__(self):
|
||||||
|
super(Plugin, self).__init__()
|
||||||
|
|
||||||
|
|
||||||
|
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||||
|
if isinstance(event, Code_Event_Types.FocusedViewEvent):
|
||||||
|
markdown_preview._do_markdown_translate(event.view.get_buffer())
|
||||||
|
elif isinstance(event, Code_Event_Types.TextChangedEvent):
|
||||||
|
markdown_preview._do_markdown_translate(event.buffer)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
separator_right = self.requests_ui_element("separator-right")
|
||||||
|
markdown_preview.set_relative_to(separator_right)
|
||||||
|
|
||||||
|
event = Event_Factory.create_event("register_command",
|
||||||
|
command_name = "tggle_markdown_preview",
|
||||||
|
command = Handler,
|
||||||
|
binding_mode = "released",
|
||||||
|
binding = "<Shift><Control>m"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.message_to("source_views", event)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class Handler:
|
||||||
|
@staticmethod
|
||||||
|
def execute(
|
||||||
|
view: any
|
||||||
|
):
|
||||||
|
logger.debug("Command: Markdown Preview")
|
||||||
|
|
||||||
|
if not markdown_preview.can_hide:
|
||||||
|
markdown_preview.can_hide = True
|
||||||
|
|
||||||
|
markdown_preview.popdown() if markdown_preview.is_visible() else markdown_preview.popup()
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
# Python imports
|
# Python imports
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
import gi
|
|
||||||
gi.require_version('Gtk', '3.0')
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||||
@@ -62,4 +59,5 @@ class Handler:
|
|||||||
view: any
|
view: any
|
||||||
):
|
):
|
||||||
logger.debug("Command: Search/Replace")
|
logger.debug("Command: Search/Replace")
|
||||||
|
|
||||||
search_replace.hide() if search_replace.is_visible() else search_replace.show()
|
search_replace.hide() if search_replace.is_visible() else search_replace.show()
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Markdown Preview",
|
|
||||||
"author": "ITDominator",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"support": "",
|
|
||||||
"requests": {
|
|
||||||
"pass_events": true,
|
|
||||||
"pass_ui_objects": ["separator_right"],
|
|
||||||
"bind_keys": ["Markdown Preview||tggle_markdown_preview:<Shift><Control>m"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!-- Generated with glade 3.40.0 -->
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk+" version="3.24"/>
|
|
||||||
<requires lib="webkit2gtk" version="2.28"/>
|
|
||||||
<object class="GtkImage" id="settings_img">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="stock">gtk-justify-fill</property>
|
|
||||||
</object>
|
|
||||||
<object class="WebKitSettings" type-func="webkit_settings_get_type" id="web_view_settings">
|
|
||||||
<property name="enable-offline-web-application-cache">False</property>
|
|
||||||
<property name="enable-html5-local-storage">False</property>
|
|
||||||
<property name="enable-html5-database">False</property>
|
|
||||||
<property name="enable-xss-auditor">False</property>
|
|
||||||
<property name="enable-hyperlink-auditing">False</property>
|
|
||||||
<property name="enable-tabs-to-links">False</property>
|
|
||||||
<property name="enable-fullscreen">False</property>
|
|
||||||
<property name="print-backgrounds">False</property>
|
|
||||||
<property name="enable-webaudio">False</property>
|
|
||||||
<property name="enable-page-cache">False</property>
|
|
||||||
<property name="user-agent">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15</property>
|
|
||||||
<property name="enable-accelerated-2d-canvas">True</property>
|
|
||||||
<property name="allow-file-access-from-file-urls">True</property>
|
|
||||||
<property name="allow-universal-access-from-file-urls">True</property>
|
|
||||||
<property name="enable-webrtc">True</property>
|
|
||||||
</object>
|
|
||||||
<object class="GtkPopover" id="markdown_preview_dialog">
|
|
||||||
<property name="width-request">620</property>
|
|
||||||
<property name="height-request">480</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="vexpand">True</property>
|
|
||||||
<property name="position">left</property>
|
|
||||||
<property name="modal">False</property>
|
|
||||||
<property name="transitions-enabled">False</property>
|
|
||||||
<property name="constrain-to">none</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkBox">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="hexpand">True</property>
|
|
||||||
<property name="vexpand">True</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButtonBox">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="layout-style">end</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkToggleButton">
|
|
||||||
<property name="label">gtk-media-pause</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">True</property>
|
|
||||||
<property name="receives-default">True</property>
|
|
||||||
<property name="use-stock">True</property>
|
|
||||||
<property name="always-show-image">True</property>
|
|
||||||
<signal name="toggled" handler="_tggle_preview_updates" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">True</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="sensitive">False</property>
|
|
||||||
<property name="can-focus">True</property>
|
|
||||||
<property name="receives-default">True</property>
|
|
||||||
<property name="image">settings_img</property>
|
|
||||||
<signal name="clicked" handler="_handle_settings" swapped="no"/>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">True</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">False</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkScrolledWindow">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">True</property>
|
|
||||||
<property name="shadow-type">in</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkViewport">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<child>
|
|
||||||
<object class="WebKitWebView" type-func="webkit_web_view_get_type" id="markdown_view">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can-focus">False</property>
|
|
||||||
<property name="settings">web_view_settings</property>
|
|
||||||
<property name="is-ephemeral">True</property>
|
|
||||||
<property name="is-muted">True</property>
|
|
||||||
<property name="default-content-security-policy">*</property>
|
|
||||||
<child>
|
|
||||||
<placeholder/>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="expand">True</property>
|
|
||||||
<property name="fill">True</property>
|
|
||||||
<property name="position">1</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
# Python imports
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Lib imports
|
|
||||||
import gi
|
|
||||||
gi.require_version('Gtk', '3.0')
|
|
||||||
gi.require_version('Gdk', '3.0')
|
|
||||||
gi.require_version('WebKit2', '4.0')
|
|
||||||
from gi.repository import Gtk
|
|
||||||
from gi.repository import Gdk
|
|
||||||
from gi.repository import WebKit2
|
|
||||||
|
|
||||||
# Application imports
|
|
||||||
from . import markdown
|
|
||||||
from .markdown_template_mixin import MarkdownTemplateMixin
|
|
||||||
from plugins.plugin_base import PluginBase
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Plugin(MarkdownTemplateMixin, PluginBase):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self.name = "Markdown Preview" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
|
|
||||||
# where self.name should not be needed for message comms
|
|
||||||
self.path = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
self._GLADE_FILE = f"{self.path}/markdown_preview.glade"
|
|
||||||
|
|
||||||
self.is_preview_paused = False
|
|
||||||
self.is_md_file = False
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
WebKit2.WebView() # Need one initialized for webview to work from glade file
|
|
||||||
|
|
||||||
self._builder = Gtk.Builder()
|
|
||||||
self._builder.add_from_file(self._GLADE_FILE)
|
|
||||||
self._connect_builder_signals(self, self._builder)
|
|
||||||
|
|
||||||
separator_right = self._ui_objects[0]
|
|
||||||
self._markdown_dialog = self._builder.get_object("markdown_preview_dialog")
|
|
||||||
self._markdown_view = self._builder.get_object("markdown_view")
|
|
||||||
self._web_view_settings = self._builder.get_object("web_view_settings")
|
|
||||||
|
|
||||||
self._markdown_dialog.set_relative_to(separator_right)
|
|
||||||
self._markdown_view.set_settings(self._web_view_settings)
|
|
||||||
self._markdown_view.set_background_color(Gdk.RGBA(0, 0, 0, 0.0))
|
|
||||||
|
|
||||||
|
|
||||||
def generate_reference_ui_element(self):
|
|
||||||
...
|
|
||||||
|
|
||||||
def subscribe_to_events(self):
|
|
||||||
self._event_system.subscribe("tggle_markdown_preview", self._tggle_markdown_preview)
|
|
||||||
self._event_system.subscribe("set_active_src_view", self._set_active_src_view)
|
|
||||||
self._event_system.subscribe("buffer_changed", self._do_markdown_translate)
|
|
||||||
|
|
||||||
def _buffer_changed_first_load(self, buffer):
|
|
||||||
self._buffer = buffer
|
|
||||||
|
|
||||||
self._do_markdown_translate(buffer)
|
|
||||||
|
|
||||||
def _set_active_src_view(self, source_view):
|
|
||||||
self._active_src_view = source_view
|
|
||||||
self._buffer = self._active_src_view.get_buffer()
|
|
||||||
|
|
||||||
self._do_markdown_translate(self._buffer)
|
|
||||||
|
|
||||||
def _handle_settings(self, widget = None, eve = None):
|
|
||||||
...
|
|
||||||
|
|
||||||
def _tggle_preview_updates(self, widget = None, eve = None):
|
|
||||||
self.is_preview_paused = not self.is_preview_paused
|
|
||||||
widget.set_active(self.is_preview_paused)
|
|
||||||
|
|
||||||
if not self.is_preview_paused:
|
|
||||||
self._do_markdown_translate(self._buffer)
|
|
||||||
|
|
||||||
def _tggle_markdown_preview(self, widget = None, eve = None):
|
|
||||||
if not self._active_src_view: return
|
|
||||||
|
|
||||||
is_visible = self._markdown_dialog.is_visible()
|
|
||||||
buffer = self._active_src_view.get_buffer()
|
|
||||||
data = None
|
|
||||||
|
|
||||||
if not is_visible:
|
|
||||||
self._markdown_dialog.popup();
|
|
||||||
self._do_markdown_translate(buffer)
|
|
||||||
elif not data and is_visible:
|
|
||||||
self._markdown_dialog.popdown()
|
|
||||||
|
|
||||||
def _do_markdown_translate(self, buffer):
|
|
||||||
if self.is_preview_paused: return
|
|
||||||
|
|
||||||
self.is_markdown_check()
|
|
||||||
is_visible = self._markdown_dialog.is_visible()
|
|
||||||
if not is_visible or not self.is_md_file: return
|
|
||||||
self.render_markdown(buffer)
|
|
||||||
|
|
||||||
def render_markdown(self, buffer):
|
|
||||||
start_iter = buffer.get_start_iter()
|
|
||||||
end_iter = buffer.get_end_iter()
|
|
||||||
text = buffer.get_text(start_iter, end_iter, include_hidden_chars = False)
|
|
||||||
html = markdown.markdown(text)
|
|
||||||
|
|
||||||
path = self._active_src_view.get_current_file().get_parent().get_path()
|
|
||||||
data = self.wrap_html_to_body(html)
|
|
||||||
self._markdown_view.load_html(content = data, base_uri = f"file://{path}/")
|
|
||||||
|
|
||||||
def is_markdown_check(self):
|
|
||||||
self.is_md_file = self._active_src_view.get_filetype() == "markdown"
|
|
||||||
if not self.is_md_file:
|
|
||||||
data = self.wrap_html_to_body("<h1>Not a Markdown file...</h1>")
|
|
||||||
self._markdown_view.load_html(content = data, base_uri = None)
|
|
||||||
@@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..widgets.separator_widget import Separator
|
||||||
from ..widgets.vte_widget import VteWidget
|
from ..widgets.vte_widget import VteWidget
|
||||||
|
|
||||||
|
|
||||||
@@ -42,4 +43,6 @@ class FooterContainer(Gtk.Box):
|
|||||||
vte_widget = VteWidget()
|
vte_widget = VteWidget()
|
||||||
|
|
||||||
vte_widget.hide()
|
vte_widget.hide()
|
||||||
self.add( vte_widget )
|
self.add( vte_widget )
|
||||||
|
|
||||||
|
self.add( Separator("separator-footer", 0) )
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..widgets.separator_widget import Separator
|
||||||
from ..widgets.controls.transparency_scale import TransparencyScale
|
from ..widgets.controls.transparency_scale import TransparencyScale
|
||||||
|
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ class HeaderContainer(Gtk.Box):
|
|||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
widget_registery.expose_object("header-container", self)
|
widget_registery.expose_object("header-container", self)
|
||||||
|
|
||||||
|
self.add( Separator("separator-header", 0) )
|
||||||
self.add( TransparencyScale() )
|
self.add( TransparencyScale() )
|
||||||
|
|
||||||
def tggl_top_main_menubar(self):
|
def tggl_top_main_menubar(self):
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..widgets.separator_widget import Separator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ class LeftContainer(Gtk.Box):
|
|||||||
self.ctx = self.get_style_context()
|
self.ctx = self.get_style_context()
|
||||||
self.ctx.add_class("left-container")
|
self.ctx.add_class("left-container")
|
||||||
|
|
||||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||||
self.set_vexpand(True)
|
self.set_vexpand(True)
|
||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
@@ -36,4 +37,5 @@ class LeftContainer(Gtk.Box):
|
|||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
widget_registery.expose_object("left-container", self)
|
widget_registery.expose_object("left-container", self)
|
||||||
|
self.add( Separator("separator-left", 1) )
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from ..widgets.separator_widget import Separator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +26,7 @@ class RightContainer(Gtk.Box):
|
|||||||
self.ctx = self.get_style_context()
|
self.ctx = self.get_style_context()
|
||||||
self.ctx.add_class("right-container")
|
self.ctx.add_class("right-container")
|
||||||
|
|
||||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||||
self.set_vexpand(True)
|
self.set_vexpand(True)
|
||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
@@ -36,4 +37,4 @@ class RightContainer(Gtk.Box):
|
|||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
widget_registery.expose_object("right-container", self)
|
widget_registery.expose_object("right-container", self)
|
||||||
|
self.add( Separator("separator-right", 1) )
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from gi.repository import Gtk
|
|||||||
from gi.repository import GtkSource
|
from gi.repository import GtkSource
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
|
from libs.event_factory import Code_Event_Types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -26,16 +27,16 @@ class ProviderResponseCacheBase:
|
|||||||
self._icon_theme = Gtk.IconTheme.get_default()
|
self._icon_theme = Gtk.IconTheme.get_default()
|
||||||
|
|
||||||
|
|
||||||
def process_file_load(self, buffer: GtkSource.Buffer):
|
def process_file_load(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||||
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_load' not implemented...")
|
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_load' not implemented...")
|
||||||
|
|
||||||
def process_file_close(self, buffer: GtkSource.Buffer):
|
def process_file_close(self, event: Code_Event_Types.RemovedFileEvent):
|
||||||
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_close' not implemented...")
|
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_close' not implemented...")
|
||||||
|
|
||||||
def process_file_save(self, buffer: GtkSource.Buffer):
|
def process_file_save(self, event: Code_Event_Types.SavedFileEvent):
|
||||||
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_save' not implemented...")
|
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_file_save' not implemented...")
|
||||||
|
|
||||||
def process_file_change(self, buffer: GtkSource.Buffer):
|
def process_file_change(self, event: Code_Event_Types.TextChangedEvent):
|
||||||
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_change' not implemented...")
|
raise ProviderResponseCacheException("ProviderResponseCacheBase 'process_change' not implemented...")
|
||||||
|
|
||||||
def filter(self, word: str) -> list[dict]:
|
def filter(self, word: str) -> list[dict]:
|
||||||
|
|||||||
@@ -45,8 +45,11 @@ class SourceFile(GtkSource.File):
|
|||||||
def _changed(self, buffer: SourceBuffer):
|
def _changed(self, buffer: SourceBuffer):
|
||||||
self.check_file_on_disk()
|
self.check_file_on_disk()
|
||||||
|
|
||||||
event = Event_Factory.create_event("text_changed", buffer = buffer)
|
event = Event_Factory.create_event(
|
||||||
event.file = self
|
"text_changed",
|
||||||
|
file = self,
|
||||||
|
buffer = buffer
|
||||||
|
)
|
||||||
self.emit(event)
|
self.emit(event)
|
||||||
|
|
||||||
if self.is_deleted():
|
if self.is_deleted():
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class SourceView(GtkSource.View, SourceViewDnDMixin):
|
|||||||
language = buffer.get_language()
|
language = buffer.get_language()
|
||||||
|
|
||||||
if language.get_id() == "json":
|
if language.get_id() == "json":
|
||||||
self._load_pretify_json(view, menu)
|
self._load_prettify_json(view, menu)
|
||||||
|
|
||||||
menu.show_all()
|
menu.show_all()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ class WebkitUI(WebKit2.WebView):
|
|||||||
|
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
self._load_view()
|
|
||||||
self._setup_content_manager()
|
self._setup_content_manager()
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
@@ -36,15 +35,6 @@ class WebkitUI(WebKit2.WebView):
|
|||||||
def _load_settings(self):
|
def _load_settings(self):
|
||||||
self.set_settings( WebkitUISettings() )
|
self.set_settings( WebkitUISettings() )
|
||||||
|
|
||||||
def _load_view(self):
|
|
||||||
path = settings_manager.get_context_path()
|
|
||||||
data = None
|
|
||||||
|
|
||||||
with open(f"{path}/index.html", "r") as f:
|
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
self.load_html(content = data, base_uri = f"file://{path}/")
|
|
||||||
|
|
||||||
def _setup_content_manager(self):
|
def _setup_content_manager(self):
|
||||||
content_manager = self.get_user_content_manager()
|
content_manager = self.get_user_content_manager()
|
||||||
content_manager.connect("script-message-received", self._process_js_message)
|
content_manager.connect("script-message-received", self._process_js_message)
|
||||||
@@ -60,6 +50,22 @@ class WebkitUI(WebKit2.WebView):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(e)
|
logger.info(e)
|
||||||
|
|
||||||
|
def load_url(self, url: str = ""):
|
||||||
|
if not url:
|
||||||
|
url = "https://duckduckgo.com/"
|
||||||
|
|
||||||
|
self.load_uri(url)
|
||||||
|
|
||||||
|
def load_context_base_path(self, path: str = ""):
|
||||||
|
if not path:
|
||||||
|
path = settings_manager.path_manager.get_context_path()
|
||||||
|
|
||||||
|
data = None
|
||||||
|
with open(f"{path}/index.html", "r") as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
self.load_html(content = data, base_uri = f"file://{path}")
|
||||||
|
|
||||||
def ui_message(self, message, mtype):
|
def ui_message(self, message, mtype):
|
||||||
command = f"displayMessage('{message}', '{mtype}', '3')"
|
command = f"displayMessage('{message}', '{mtype}', '3')"
|
||||||
self.run_javascript(command, None, None)
|
self.run_javascript(command, None, None)
|
||||||
|
|||||||
@@ -39,4 +39,64 @@ class WebkitUISettings(WebKit2.Settings):
|
|||||||
self.set_enable_webaudio(True)
|
self.set_enable_webaudio(True)
|
||||||
self.set_enable_accelerated_2d_canvas(True)
|
self.set_enable_accelerated_2d_canvas(True)
|
||||||
|
|
||||||
self.set_user_agent(f"{APP_NAME}")
|
self.set_user_agent(
|
||||||
|
f"Mozilla/5.0 (macOS, AArch64) {APP_NAME}/1.0 Chrome/140.0.0 AppleWebKit/537.36 Safari/537.36"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Note: Most "browser" like setup I could think of.
|
||||||
|
def other_set_default_settings(self):
|
||||||
|
# Usability
|
||||||
|
self.set_property('enable-fullscreen', True)
|
||||||
|
self.set_property('print-backgrounds', True)
|
||||||
|
self.set_property('enable-frame-flattening', False)
|
||||||
|
self.set_property('enable-plugins', True)
|
||||||
|
self.set_property('enable-java', False)
|
||||||
|
self.set_property('enable-resizable-text-areas', True)
|
||||||
|
self.set_property('zoom-text-only', False)
|
||||||
|
self.set_property('enable-smooth-scrolling', True)
|
||||||
|
self.set_property('enable-back-forward-navigation-gestures', False)
|
||||||
|
self.set_property('media-playback-requires-user-gesture', False)
|
||||||
|
self.set_property('enable-tabs-to-links', True)
|
||||||
|
self.set_property('enable-caret-browsing', False)
|
||||||
|
|
||||||
|
# Security
|
||||||
|
# self.set_property('user-agent', 'Mozilla/5.0 (X11; Generic; Linux x86-64) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Safari/605.1.15')
|
||||||
|
self.set_property('user-agent', f"Mozilla/5.0 (macOS, AArch64) {APP_NAME}/1.0 Chrome/140.0.0 AppleWebKit/537.36 Safari/537.36")
|
||||||
|
self.set_property('enable-private-browsing', False)
|
||||||
|
self.set_property('enable-xss-auditor', True)
|
||||||
|
self.set_property('enable-hyperlink-auditing', False)
|
||||||
|
self.set_property('enable-site-specific-quirks', True)
|
||||||
|
self.set_property('enable-offline-web-application-cache', True)
|
||||||
|
self.set_property('enable-page-cache', True)
|
||||||
|
self.set_property('allow-modal-dialogs', True)
|
||||||
|
self.set_property('enable-html5-local-storage', True)
|
||||||
|
self.set_property('enable-html5-database', True)
|
||||||
|
self.set_property('allow-file-access-from-file-urls', True)
|
||||||
|
self.set_property('allow-universal-access-from-file-urls', False)
|
||||||
|
self.set_property('enable-dns-prefetching', False)
|
||||||
|
|
||||||
|
# Media stuff
|
||||||
|
self.set_hardware_acceleration_policy(0)
|
||||||
|
# self.set_property('hardware-acceleration-policy', 'on-demand')
|
||||||
|
self.set_property('enable-webgl', True)
|
||||||
|
self.set_property('enable-webaudio', True)
|
||||||
|
self.set_property('enable-accelerated-2d-canvas', True)
|
||||||
|
self.set_property('auto-load-images', True)
|
||||||
|
self.set_property('enable-media-capabilities', True)
|
||||||
|
self.set_property('enable-media-stream', True)
|
||||||
|
self.set_property('enable-mediasource', True)
|
||||||
|
self.set_property('enable-encrypted-media', True)
|
||||||
|
self.set_property('media-playback-allows-inline', True)
|
||||||
|
|
||||||
|
# JS
|
||||||
|
self.set_property('enable-javascript', True)
|
||||||
|
self.set_property('enable-javascript-markup', True)
|
||||||
|
self.set_property('javascript-can-access-clipboard', False)
|
||||||
|
self.set_property('javascript-can-open-windows-automatically', False)
|
||||||
|
|
||||||
|
# Debugging
|
||||||
|
self.set_property('enable-developer-extras', False)
|
||||||
|
self.set_property('enable-write-console-messages-to-stdout', False)
|
||||||
|
self.set_property('draw-compositing-indicators', False)
|
||||||
|
self.set_property('enable-mock-capture-devices', False)
|
||||||
|
self.set_property('enable-spatial-navigation', False)
|
||||||
|
|||||||
Reference in New Issue
Block a user