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": "",
|
"support": "",
|
||||||
"requests": {
|
"requests": {
|
||||||
"ui_target": "plugin_control_list",
|
"ui_target": "plugin_control_list",
|
||||||
"pass_fm_events": "true",
|
"pass_events": "true",
|
||||||
"bind_keys": ["Example Plugin||send_message:<Control>f"]
|
"bind_keys": ["Example Plugin||send_message:<Control>f"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,11 @@ 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.save_file_dialog import SaveFileDialog
|
from .widgets.save_file_dialog import SaveFileDialog
|
||||||
|
from .widgets.base.general_info_widget import GeneralInfoWidget
|
||||||
from .widgets.base.banner_controls import BannerControls
|
from .widgets.base.banner_controls import BannerControls
|
||||||
from .editors_container import EditorsContainer
|
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):
|
def _setup_styling(self):
|
||||||
self.set_orientation(1)
|
self.set_orientation(1) # VERTICAL = 1
|
||||||
|
|
||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
...
|
...
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
SaveFileDialog()
|
SaveFileDialog()
|
||||||
self.add(BannerControls())
|
|
||||||
GeneralInfoWidget()
|
GeneralInfoWidget()
|
||||||
|
|
||||||
|
self.add(BannerControls())
|
||||||
|
self.add(Separator("separator_top"))
|
||||||
self.add(EditorsContainer())
|
self.add(EditorsContainer())
|
||||||
|
self.add(Separator("separator_botton"))
|
||||||
|
|
|
@ -30,6 +30,8 @@ class BannerControls(Gtk.Box):
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
self.set_orientation(0)
|
self.set_orientation(0)
|
||||||
|
self.set_margin_top(5)
|
||||||
|
self.set_margin_bottom(5)
|
||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
...
|
...
|
||||||
|
|
|
@ -52,8 +52,6 @@ class EditorControllerMixin:
|
||||||
self.move_lines_down(source_view)
|
self.move_lines_down(source_view)
|
||||||
if action == "keyboard_tggl_comment":
|
if action == "keyboard_tggl_comment":
|
||||||
self.keyboard_tggl_comment(source_view)
|
self.keyboard_tggl_comment(source_view)
|
||||||
if action == "do_text_search":
|
|
||||||
self.do_text_search(source_view, query)
|
|
||||||
if action == "set_buffer_language":
|
if action == "set_buffer_language":
|
||||||
self.set_buffer_language(source_view, query)
|
self.set_buffer_language(source_view, query)
|
||||||
if action == "set_buffer_style":
|
if action == "set_buffer_style":
|
||||||
|
|
|
@ -125,12 +125,8 @@ class EditorEventsMixin:
|
||||||
def keyboard_tggl_comment(self, source_view):
|
def keyboard_tggl_comment(self, source_view):
|
||||||
source_view.keyboard_tggl_comment()
|
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"):
|
def set_buffer_language(self, source_view, language = "python3"):
|
||||||
source_view.set_buffer_language(language)
|
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)
|
source_view.set_buffer_style(style)
|
||||||
|
|
|
@ -92,17 +92,12 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
start_box = Gtk.Box()
|
start_box = Gtk.Box()
|
||||||
end_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 = Gtk.Button()
|
||||||
add_btn.set_image( Gtk.Image.new_from_icon_name("add", 4) )
|
add_btn.set_image( Gtk.Image.new_from_icon_name("add", 4) )
|
||||||
add_btn.set_always_show_image(True)
|
add_btn.set_always_show_image(True)
|
||||||
add_btn.connect("released", self.create_view)
|
add_btn.connect("released", self.create_view)
|
||||||
|
|
||||||
end_box.add(add_btn)
|
end_box.add(add_btn)
|
||||||
end_box.add(search)
|
|
||||||
|
|
||||||
start_box.show_all()
|
start_box.show_all()
|
||||||
end_box.show_all()
|
end_box.show_all()
|
||||||
|
@ -210,6 +205,3 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook):
|
||||||
|
|
||||||
def _keyboard_save_file_as(self):
|
def _keyboard_save_file_as(self):
|
||||||
self.action_controller("save_file_as")
|
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):
|
if isinstance(requests["bind_keys"], list):
|
||||||
loading_data["bind_keys"] = requests["bind_keys"]
|
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
|
return self._plugin, loading_data
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Python imports
|
# Python imports
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import inspect
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
|
||||||
|
@ -12,7 +13,8 @@ class PluginBaseException(Exception):
|
||||||
|
|
||||||
|
|
||||||
class PluginBase:
|
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
|
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
|
# where self.name should not be needed for message comms
|
||||||
|
|
||||||
|
@ -36,13 +38,6 @@ class PluginBase:
|
||||||
"""
|
"""
|
||||||
raise PluginBaseException("Method hasn't been overriden...")
|
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):
|
def set_ui_object_collection(self, ui_objects):
|
||||||
"""
|
"""
|
||||||
Requests Key: "pass_ui_objects": [""]
|
Requests Key: "pass_ui_objects": [""]
|
||||||
|
@ -51,9 +46,45 @@ class PluginBase:
|
||||||
"""
|
"""
|
||||||
self._ui_objects = ui_objects
|
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 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:
|
def clear_children(self, widget: type) -> None:
|
||||||
""" Clear children of a gtk widget. """
|
""" Clear children of a gtk widget. """
|
||||||
|
|
|
@ -53,7 +53,7 @@ class PluginsController:
|
||||||
self.reload_plugins(file)
|
self.reload_plugins(file)
|
||||||
|
|
||||||
def load_plugins(self, file: str = None) -> None:
|
def load_plugins(self, file: str = None) -> None:
|
||||||
print(f"Loading plugins...")
|
logger.info(f"Loading plugins...")
|
||||||
parent_path = os.getcwd()
|
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)]:
|
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)
|
module = self.load_plugin_module(path, folder, target)
|
||||||
self.execute_plugin(module, plugin, loading_data)
|
self.execute_plugin(module, plugin, loading_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
logger.info(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||||
traceback.print_exc()
|
logger.debug("Trace: ", traceback.print_exc())
|
||||||
|
|
||||||
os.chdir(parent_path)
|
os.chdir(parent_path)
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class PluginsController:
|
||||||
plugin.reference.set_ui_object_collection( loading_data["pass_ui_objects"] )
|
plugin.reference.set_ui_object_collection( loading_data["pass_ui_objects"] )
|
||||||
|
|
||||||
if "pass_events" in keys:
|
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()
|
plugin.reference.subscribe_to_events()
|
||||||
|
|
||||||
if "bind_keys" in keys:
|
if "bind_keys" in keys:
|
||||||
|
@ -116,4 +116,4 @@ class PluginsController:
|
||||||
self._plugin_collection.append(plugin)
|
self._plugin_collection.append(plugin)
|
||||||
|
|
||||||
def reload_plugins(self, file: str = None) -> None:
|
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.keymap = Gdk.Keymap.get_default()
|
||||||
self.configure({})
|
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):
|
def configure(self, bindings):
|
||||||
""" Accept new bindings and reconfigure with them """
|
""" Accept new bindings and reconfigure with them """
|
||||||
self.keys = bindings
|
self.keys = bindings
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
"tear_down" : "<Control>q",
|
"tear_down" : "<Control>q",
|
||||||
"toggle_highlight_line" : "<Control>h",
|
"toggle_highlight_line" : "<Control>h",
|
||||||
"open_files" : "<Control>o",
|
"open_files" : "<Control>o",
|
||||||
|
"move_lines_up" : "<Control>Up",
|
||||||
|
"move_lines_down" : "<Control>Down",
|
||||||
"keyboard_create_tab" : "<Control>t",
|
"keyboard_create_tab" : "<Control>t",
|
||||||
"keyboard_close_tab" : "<Control>w",
|
"keyboard_close_tab" : "<Control>w",
|
||||||
"keyboard_save_file" : "<Control>s",
|
"keyboard_save_file" : "<Control>s",
|
||||||
"keyboard_insert_mark" : "<Control>m",
|
"keyboard_insert_mark" : "<Control>m",
|
||||||
|
"keyboard_tggl_comment" : "<Control>slash",
|
||||||
"keyboard_clear_marks" : "<Shift><Control>m",
|
"keyboard_clear_marks" : "<Shift><Control>m",
|
||||||
"keyboard_save_file_as" : "<Shift><Control>s",
|
"keyboard_save_file_as" : "<Shift><Control>s",
|
||||||
"keyboard_up" : "Up",
|
"keyboard_up" : "Up",
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
/* ---- make most desired things base transparent ---- */
|
/* ---- make most desired things base transparent ---- */
|
||||||
|
popover,
|
||||||
|
/* popover *, */
|
||||||
|
popover > box
|
||||||
window > box,
|
window > box,
|
||||||
window > box > box,
|
window > box > box,
|
||||||
window > box > box > paned,
|
window > box > box > paned,
|
||||||
|
@ -57,6 +60,13 @@ notebook > stack > scrolledwindow > textview {
|
||||||
color: rgba(255, 255, 255, 1);
|
color: rgba(255, 255, 255, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* any popover */
|
||||||
|
popover {
|
||||||
|
background: rgba(39, 43, 52, 0.86);
|
||||||
|
color: rgba(255, 255, 255, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ---- miniview properties ---- */
|
/* ---- miniview properties ---- */
|
||||||
/* the mini view container of text */
|
/* the mini view container of text */
|
||||||
.mini-view > text {
|
.mini-view > text {
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
<property name="margin-right">10</property>
|
<property name="margin-right">10</property>
|
||||||
<property name="margin-start">10</property>
|
<property name="margin-start">10</property>
|
||||||
<property name="margin-end">10</property>
|
<property name="margin-end">10</property>
|
||||||
<property name="margin-top">6</property>
|
<property name="margin-top">5</property>
|
||||||
<property name="margin-bottom">6</property>
|
|
||||||
<property name="spacing">15</property>
|
<property name="spacing">15</property>
|
||||||
<property name="baseline-position">top</property>
|
<property name="baseline-position">top</property>
|
||||||
<child type="center">
|
<child type="center">
|
||||||
|
|
Loading…
Reference in New Issue