generated from itdominator/Python-With-Gtk-Template
Worked on the plugin system; added preliminary search and replace plugin
This commit is contained in:
parent
2caf381742
commit
dd086ec1d6
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
Pligin Module
|
||||
"""
|
|
@ -0,0 +1,3 @@
|
|||
"""
|
||||
Pligin Package
|
||||
"""
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"manifest": {
|
||||
"name": "Search/Replace",
|
||||
"author": "ITDominator",
|
||||
"version": "0.0.1",
|
||||
"support": "",
|
||||
"requests": {
|
||||
"pass_events": "true",
|
||||
"pass_ui_objects": ["separator_botton"],
|
||||
"bind_keys": ["Search/Replace||tggl_search_replace:<Control>f"]
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
# Python imports
|
||||
import os
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from plugins.plugin_base import PluginBase
|
||||
|
||||
|
||||
|
||||
|
||||
class Plugin(PluginBase):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.name = "Search/Replace" # 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}/search_replace.glade"
|
||||
|
||||
self._search_replace_dialog = None
|
||||
self._find_entry = None
|
||||
self._replace_entry = None
|
||||
self._active_src_view = None
|
||||
|
||||
self.use_regex = False
|
||||
self.use_case_sensitive = False
|
||||
self.use_selection_only_scan = False
|
||||
self.use_fuzzy_search = False
|
||||
self.highlight_color = "#FBF719"
|
||||
self.text_color = "#000000"
|
||||
|
||||
|
||||
def run(self):
|
||||
self._builder = Gtk.Builder()
|
||||
self._builder.add_from_file(self._GLADE_FILE)
|
||||
self._connect_builder_signals(self, self._builder)
|
||||
|
||||
separator_botton = self._ui_objects[0]
|
||||
self._search_replace_dialog = self._builder.get_object("search_replace_dialog")
|
||||
self._find_status_lbl = self._builder.get_object("find_status_lbl")
|
||||
self._find_options_lbl = self._builder.get_object("find_options_lbl")
|
||||
|
||||
self._find_entry = self._builder.get_object("find_entry")
|
||||
self._replace_entry = self._builder.get_object("replace_entry")
|
||||
|
||||
self._search_replace_dialog.set_relative_to(separator_botton)
|
||||
self._search_replace_dialog.set_hexpand(True)
|
||||
|
||||
def generate_reference_ui_element(self):
|
||||
...
|
||||
|
||||
def subscribe_to_events(self):
|
||||
self._event_system.subscribe("tggl_search_replace", self._tggl_search_replace)
|
||||
self._event_system.subscribe("set_active_src_view", self._set_active_src_view)
|
||||
|
||||
def _set_active_src_view(self, source_view):
|
||||
self._active_src_view = source_view
|
||||
self.search_for_string(self._find_entry)
|
||||
|
||||
def _show_search_replace(self, widget = None, eve = None):
|
||||
self._search_replace_dialog.popup()
|
||||
|
||||
def _tggl_search_replace(self, widget = None, eve = None):
|
||||
is_visible = self._search_replace_dialog.is_visible()
|
||||
if not is_visible:
|
||||
self._search_replace_dialog.popup();
|
||||
self._find_entry.grab_focus()
|
||||
else:
|
||||
self._search_replace_dialog.popdown()
|
||||
|
||||
def tggle_regex(self, widget):
|
||||
self.use_regex = not widget.get_active()
|
||||
self._set_find_options_lbl()
|
||||
|
||||
def tggle_case_sensitive(self, widget):
|
||||
self.use_case_sensitive = not widget.get_active()
|
||||
self._set_find_options_lbl()
|
||||
|
||||
def tggle_selection_only_scan(self, widget):
|
||||
self.use_selection_only_scan = not widget.get_active()
|
||||
self._set_find_options_lbl()
|
||||
|
||||
def tggle_fuzzy_search(self, widget):
|
||||
self.use_fuzzy_search = not widget.get_active()
|
||||
self._set_find_options_lbl()
|
||||
|
||||
def _set_find_options_lbl(self):
|
||||
# Finding with Options: Case Insensitive
|
||||
# Finding with Options: Regex, Case Sensitive, Within Current Selection, Whole Word
|
||||
# Finding with Options: Regex, Case Inensitive, Within Current Selection, Whole Word
|
||||
# f"Finding with Options: {regex}, {case}, {selection}, {word}"
|
||||
...
|
||||
|
||||
def _update_status_lbl(self, total_count: int = None, query: str = None):
|
||||
if not total_count or not query: return
|
||||
|
||||
count = total_count if total_count > 0 else "No"
|
||||
plural = "s" if total_count > 1 else ""
|
||||
self._find_status_lbl.set_label(f"{count} results{plural} found for '{query}'")
|
||||
|
||||
def get_search_tag(self, buffer):
|
||||
tag_table = buffer.get_tag_table()
|
||||
search_tag = tag_table.lookup("search_tag")
|
||||
if not search_tag:
|
||||
search_tag = buffer.create_tag("search_tag", background = self.highlight_color, foreground = self.text_color)
|
||||
|
||||
buffer.remove_tag_by_name("search_tag", buffer.get_start_iter(), buffer.get_end_iter())
|
||||
return search_tag
|
||||
|
||||
def search_for_string(self, widget):
|
||||
query = widget.get_text()
|
||||
buffer = self._active_src_view.get_buffer()
|
||||
# Also clears tag from buffer so if no query we're clean in ui
|
||||
search_tag = self.get_search_tag(buffer)
|
||||
|
||||
if not query:
|
||||
self._find_status_lbl.set_label(f"Find in current buffer")
|
||||
return
|
||||
|
||||
start_itr = buffer.get_start_iter()
|
||||
end_itr = buffer.get_end_iter()
|
||||
|
||||
results, total_count = self.search(start_itr, query)
|
||||
for start, end in results:
|
||||
buffer.apply_tag(search_tag, start, end)
|
||||
self._update_status_lbl(total_count, query)
|
||||
|
||||
def search(self, start_itr = None, query = None):
|
||||
if not start_itr or not query: return None, None
|
||||
|
||||
if not self.use_case_sensitive:
|
||||
_flags = Gtk.TextSearchFlags.VISIBLE_ONLY & Gtk.TextSearchFlags.TEXT_ONLY & Gtk.TextSearchFlags.CASE_INSENSITIVE
|
||||
else:
|
||||
_flags = Gtk.TextSearchFlags.VISIBLE_ONLY & Gtk.TextSearchFlags.TEXT_ONLY
|
||||
|
||||
results = []
|
||||
while True:
|
||||
result = start_itr.forward_search(query, flags = _flags, limit = None)
|
||||
if not result: break
|
||||
|
||||
results.append(result)
|
||||
start_itr = result[1]
|
||||
|
||||
return results, len(results)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def find_next(self):
|
||||
...
|
||||
|
||||
def find_all(self):
|
||||
...
|
||||
|
||||
def replace_next(self):
|
||||
...
|
||||
|
||||
def replace_all(self):
|
||||
...
|
|
@ -0,0 +1,281 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.40.0 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<object class="GtkImage" id="close_img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="stock">gtk-close</property>
|
||||
</object>
|
||||
<object class="GtkPopover" id="search_replace_dialog">
|
||||
<property name="can-focus">False</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="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="find_status_lbl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="label" translatable="yes">Find in Current Buffer</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="find_options_lbl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="xpad">20</property>
|
||||
<property name="label" translatable="yes">Finding with Options: Case Insensitive</property>
|
||||
<property name="xalign">0</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButtonBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="layout-style">start</property>
|
||||
<child>
|
||||
<object class="GtkToggleButton">
|
||||
<property name="label" translatable="yes">.*</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Use Regex</property>
|
||||
<signal name="toggled" handler="tggle_regex" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton">
|
||||
<property name="label" translatable="yes">Aa</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Match Case</property>
|
||||
<signal name="toggled" handler="tggle_case_sensitive" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton">
|
||||
<property name="label" translatable="yes">togglebutton</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Only In Selection</property>
|
||||
<signal name="toggled" handler="tggle_selection_only_scan" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleButton">
|
||||
<property name="label" translatable="yes">togglebutton</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Whole Word</property>
|
||||
<signal name="toggled" handler="tggle_fuzzy_search" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Close Panel</property>
|
||||
<property name="image">close_img</property>
|
||||
<property name="always-show-image">True</property>
|
||||
<signal name="clicked" handler="_tggl_search_replace" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</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">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<!-- n-columns=10 n-rows=2 -->
|
||||
<object class="GtkGrid">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="column-homogeneous">True</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="find_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="placeholder-text" translatable="yes">Find in current buffer</property>
|
||||
<signal name="changed" handler="search_for_string" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">0</property>
|
||||
<property name="width">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="replace_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
<property name="placeholder-text" translatable="yes">Replace in current buffer</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">0</property>
|
||||
<property name="top-attach">1</property>
|
||||
<property name="width">8</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Replace All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Replace All</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">9</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Replace</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="focus-on-click">False</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="tooltip-text" translatable="yes">Replace Next</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">8</property>
|
||||
<property name="top-attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Find All</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">9</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Find</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-start">5</property>
|
||||
<property name="margin-end">5</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="margin-bottom">5</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left-attach">8</property>
|
||||
<property name="top-attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="padding">10</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -6,7 +6,7 @@
|
|||
"support": "",
|
||||
"requests": {
|
||||
"ui_target": "plugin_control_list",
|
||||
"pass_fm_events": "true",
|
||||
"pass_events": "true",
|
||||
"bind_keys": ["Example Plugin||send_message:<Control>f"]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@ gi.require_version('Gtk', '3.0')
|
|||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from .widgets.separator_widget import Separator
|
||||
from .widgets.save_file_dialog import SaveFileDialog
|
||||
from .widgets.base.general_info_widget import GeneralInfoWidget
|
||||
from .widgets.base.banner_controls import BannerControls
|
||||
from .editors_container import EditorsContainer
|
||||
from .widgets.base.general_info_widget import GeneralInfoWidget
|
||||
|
||||
|
||||
|
||||
|
@ -28,13 +29,17 @@ class CoreWidget(Gtk.Box):
|
|||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(1)
|
||||
self.set_orientation(1) # VERTICAL = 1
|
||||
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
SaveFileDialog()
|
||||
self.add(BannerControls())
|
||||
GeneralInfoWidget()
|
||||
|
||||
self.add(BannerControls())
|
||||
self.add(Separator("separator_top"))
|
||||
self.add(EditorsContainer())
|
||||
self.add(Separator("separator_botton"))
|
||||
|
|
|
@ -30,6 +30,8 @@ class BannerControls(Gtk.Box):
|
|||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(0)
|
||||
self.set_margin_top(5)
|
||||
self.set_margin_bottom(5)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
|
|
@ -52,8 +52,6 @@ class EditorControllerMixin:
|
|||
self.move_lines_down(source_view)
|
||||
if action == "keyboard_tggl_comment":
|
||||
self.keyboard_tggl_comment(source_view)
|
||||
if action == "do_text_search":
|
||||
self.do_text_search(source_view, query)
|
||||
if action == "set_buffer_language":
|
||||
self.set_buffer_language(source_view, query)
|
||||
if action == "set_buffer_style":
|
||||
|
|
|
@ -125,12 +125,8 @@ class EditorEventsMixin:
|
|||
def keyboard_tggl_comment(self, source_view):
|
||||
source_view.keyboard_tggl_comment()
|
||||
|
||||
def do_text_search(self, query = ""):
|
||||
# source_view.scale_down_text()
|
||||
...
|
||||
|
||||
def set_buffer_language(self, source_view, language = "python3"):
|
||||
source_view.set_buffer_language(language)
|
||||
|
||||
def set_buffer_style(self, source_view, style = "tango"):
|
||||
def set_buffer_style(self, source_view, style = settings.theming.syntax_theme):
|
||||
source_view.set_buffer_style(style)
|
||||
|
|
|
@ -92,17 +92,12 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
|||
start_box = Gtk.Box()
|
||||
end_box = Gtk.Box()
|
||||
|
||||
search = Gtk.SearchEntry()
|
||||
search.set_placeholder_text("Search...")
|
||||
search.connect("changed", self._text_search)
|
||||
|
||||
add_btn = Gtk.Button()
|
||||
add_btn.set_image( Gtk.Image.new_from_icon_name("add", 4) )
|
||||
add_btn.set_always_show_image(True)
|
||||
add_btn.connect("released", self.create_view)
|
||||
|
||||
end_box.add(add_btn)
|
||||
end_box.add(search)
|
||||
|
||||
start_box.show_all()
|
||||
end_box.show_all()
|
||||
|
@ -210,6 +205,3 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
|||
|
||||
def _keyboard_save_file_as(self):
|
||||
self.action_controller("save_file_as")
|
||||
|
||||
def _text_search(self, widget = None, eve = None):
|
||||
self.action_controller("do_text_search", widget.get_text())
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class Separator(Gtk.Separator):
|
||||
def __init__(self, id: str = None, ORIENTATION: int = 0):
|
||||
super(Separator, self).__init__()
|
||||
|
||||
builder = settings_manager.get_builder()
|
||||
if id:
|
||||
builder.expose_object(id, self)
|
||||
|
||||
self.ORIENTATION = ORIENTATION
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
# HORIZONTAL = 0, VERTICAL = 1
|
||||
self.set_orientation(self.ORIENTATION)
|
||||
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
|
@ -61,4 +61,8 @@ class ManifestProcessor:
|
|||
if isinstance(requests["bind_keys"], list):
|
||||
loading_data["bind_keys"] = requests["bind_keys"]
|
||||
|
||||
if "pass_ui_objects" in keys:
|
||||
if isinstance(requests["pass_ui_objects"], list):
|
||||
loading_data["pass_ui_objects"] = [ self._builder.get_object(obj) for obj in requests["pass_ui_objects"] ]
|
||||
|
||||
return self._plugin, loading_data
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Python imports
|
||||
import os
|
||||
import time
|
||||
import inspect
|
||||
|
||||
# Lib imports
|
||||
|
||||
|
@ -12,7 +13,8 @@ class PluginBaseException(Exception):
|
|||
|
||||
|
||||
class PluginBase:
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.name = "Example Plugin" # NOTE: Need to remove after establishing private bidirectional 1-1 message bus
|
||||
# where self.name should not be needed for message comms
|
||||
|
||||
|
@ -36,13 +38,6 @@ class PluginBase:
|
|||
"""
|
||||
raise PluginBaseException("Method hasn't been overriden...")
|
||||
|
||||
def set_event_system(self, event_system):
|
||||
"""
|
||||
Requests Key: 'pass_events': "true"
|
||||
Must define in plugin if "pass_events" is set to "true" string.
|
||||
"""
|
||||
self._event_system = event_system
|
||||
|
||||
def set_ui_object_collection(self, ui_objects):
|
||||
"""
|
||||
Requests Key: "pass_ui_objects": [""]
|
||||
|
@ -51,9 +46,45 @@ class PluginBase:
|
|||
"""
|
||||
self._ui_objects = ui_objects
|
||||
|
||||
def set_event_system(self, event_system):
|
||||
"""
|
||||
Requests Key: 'pass_events': "true"
|
||||
Must define in plugin if "pass_events" is set to "true" string.
|
||||
"""
|
||||
self._event_system = event_system
|
||||
|
||||
def subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _connect_builder_signals(self, caller_class, builder):
|
||||
classes = [caller_class]
|
||||
handlers = {}
|
||||
for c in classes:
|
||||
methods = None
|
||||
try:
|
||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||
handlers.update(methods)
|
||||
except Exception as e:
|
||||
logger.debug(repr(e))
|
||||
|
||||
builder.connect_signals(handlers)
|
||||
|
||||
def reload_package(self, plugin_path, module_dict_main=locals()):
|
||||
import importlib
|
||||
from pathlib import Path
|
||||
|
||||
def reload_package_recursive(current_dir, module_dict):
|
||||
for path in current_dir.iterdir():
|
||||
if "__init__" in str(path) or path.stem not in module_dict:
|
||||
continue
|
||||
|
||||
if path.is_file() and path.suffix == ".py":
|
||||
importlib.reload(module_dict[path.stem])
|
||||
elif path.is_dir():
|
||||
reload_package_recursive(path, module_dict[path.stem].__dict__)
|
||||
|
||||
reload_package_recursive(Path(plugin_path).parent, module_dict_main["module_dict_main"])
|
||||
|
||||
|
||||
def clear_children(self, widget: type) -> None:
|
||||
""" Clear children of a gtk widget. """
|
||||
|
|
|
@ -53,7 +53,7 @@ class PluginsController:
|
|||
self.reload_plugins(file)
|
||||
|
||||
def load_plugins(self, file: str = None) -> None:
|
||||
print(f"Loading plugins...")
|
||||
logger.info(f"Loading plugins...")
|
||||
parent_path = os.getcwd()
|
||||
|
||||
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
||||
|
@ -68,8 +68,8 @@ class PluginsController:
|
|||
module = self.load_plugin_module(path, folder, target)
|
||||
self.execute_plugin(module, plugin, loading_data)
|
||||
except Exception as e:
|
||||
print(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||
traceback.print_exc()
|
||||
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||
logger.debug("Trace: ", traceback.print_exc())
|
||||
|
||||
os.chdir(parent_path)
|
||||
|
||||
|
@ -106,7 +106,7 @@ class PluginsController:
|
|||
plugin.reference.set_ui_object_collection( loading_data["pass_ui_objects"] )
|
||||
|
||||
if "pass_events" in keys:
|
||||
plugin.reference.set_fm_event_system(event_system)
|
||||
plugin.reference.set_event_system(event_system)
|
||||
plugin.reference.subscribe_to_events()
|
||||
|
||||
if "bind_keys" in keys:
|
||||
|
@ -116,4 +116,4 @@ class PluginsController:
|
|||
self._plugin_collection.append(plugin)
|
||||
|
||||
def reload_plugins(self, file: str = None) -> None:
|
||||
print(f"Reloading plugins... stub.")
|
||||
logger.info(f"Reloading plugins... stub.")
|
||||
|
|
|
@ -42,6 +42,17 @@ class Keybindings:
|
|||
self.keymap = Gdk.Keymap.get_default()
|
||||
self.configure({})
|
||||
|
||||
def print_keys(self):
|
||||
print(self.keys)
|
||||
|
||||
def append_bindings(self, combos):
|
||||
""" Accept new binding(s) and reload """
|
||||
for item in combos:
|
||||
method, keys = item.split(":")
|
||||
self.keys[method] = keys
|
||||
|
||||
self.reload()
|
||||
|
||||
def configure(self, bindings):
|
||||
""" Accept new bindings and reconfigure with them """
|
||||
self.keys = bindings
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
"tear_down" : "<Control>q",
|
||||
"toggle_highlight_line" : "<Control>h",
|
||||
"open_files" : "<Control>o",
|
||||
"move_lines_up" : "<Control>Up",
|
||||
"move_lines_down" : "<Control>Down",
|
||||
"keyboard_create_tab" : "<Control>t",
|
||||
"keyboard_close_tab" : "<Control>w",
|
||||
"keyboard_save_file" : "<Control>s",
|
||||
"keyboard_insert_mark" : "<Control>m",
|
||||
"keyboard_tggl_comment" : "<Control>slash",
|
||||
"keyboard_clear_marks" : "<Shift><Control>m",
|
||||
"keyboard_save_file_as" : "<Shift><Control>s",
|
||||
"keyboard_up" : "Up",
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
/* ---- make most desired things base transparent ---- */
|
||||
popover,
|
||||
/* popover *, */
|
||||
popover > box
|
||||
window > box,
|
||||
window > box > box,
|
||||
window > box > box > paned,
|
||||
|
@ -57,6 +60,13 @@ notebook > stack > scrolledwindow > textview {
|
|||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
/* any popover */
|
||||
popover {
|
||||
background: rgba(39, 43, 52, 0.86);
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
|
||||
/* ---- miniview properties ---- */
|
||||
/* the mini view container of text */
|
||||
.mini-view > text {
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
<property name="margin-right">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="margin-top">5</property>
|
||||
<property name="spacing">15</property>
|
||||
<property name="baseline-position">top</property>
|
||||
<child type="center">
|
||||
|
|
Loading…
Reference in New Issue