Merge Stable Changesto Master #9
@@ -12,12 +12,14 @@ from ..widgets.file_preview_widget import FilePreviewWidget
 | 
			
		||||
def threaded(fn):
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
 | 
			
		||||
 | 
			
		||||
    return wrapper
 | 
			
		||||
 | 
			
		||||
# NOTE: Threads WILL die with parent's destruction.
 | 
			
		||||
def daemon_threaded(fn):
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
 | 
			
		||||
 | 
			
		||||
    return wrapper
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +27,7 @@ class FileSearchMixin:
 | 
			
		||||
    def _run_find_file_query(self, widget=None, eve=None):
 | 
			
		||||
        self._handle_find_file_query(query=widget)
 | 
			
		||||
 | 
			
		||||
    # TODO: Merge this logic with nearly the exact same thing in grep_search_mixin
 | 
			
		||||
    @daemon_threaded
 | 
			
		||||
    def _handle_find_file_query(self, widget=None, eve=None, query=None):
 | 
			
		||||
        # NOTE: Freeze IPC consumption
 | 
			
		||||
@@ -33,19 +36,15 @@ class FileSearchMixin:
 | 
			
		||||
 | 
			
		||||
        # NOTE: Kill the former process
 | 
			
		||||
        if self._list_proc:
 | 
			
		||||
            if self._list_proc.poll():
 | 
			
		||||
                self._list_proc.send_signal(signal.SIGKILL)
 | 
			
		||||
                while self._list_proc.poll():
 | 
			
		||||
                    pass
 | 
			
		||||
            if self._list_proc.poll() == None:
 | 
			
		||||
                self._list_proc.terminate()
 | 
			
		||||
                while self._list_proc.poll() == None:
 | 
			
		||||
                    ...
 | 
			
		||||
 | 
			
		||||
            self._list_proc = None
 | 
			
		||||
            else:
 | 
			
		||||
                self._list_proc = None
 | 
			
		||||
 | 
			
		||||
        # NOTE: Clear children from ui and make sure ui thread redraws
 | 
			
		||||
        GLib.idle_add(self.clear_children, self._file_list)
 | 
			
		||||
        while len(self._file_list.get_children()) > 0:
 | 
			
		||||
            time.sleep(0.2)
 | 
			
		||||
        GLib.idle_add(self.reset_file_list_box)
 | 
			
		||||
 | 
			
		||||
        # NOTE: If query create new process and do all new loop.
 | 
			
		||||
        self.pause_fifo_update = False
 | 
			
		||||
@@ -62,9 +61,6 @@ class FileSearchMixin:
 | 
			
		||||
            self._list_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None)
 | 
			
		||||
 | 
			
		||||
    def _load_file_ui(self, data):
 | 
			
		||||
        if self.pause_fifo_update:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if not data in ("", None):
 | 
			
		||||
            jdata  = json.loads( data )
 | 
			
		||||
            target = jdata[0]
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,14 @@ from ..widgets.grep_preview_widget import GrepPreviewWidget
 | 
			
		||||
def threaded(fn):
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
 | 
			
		||||
 | 
			
		||||
    return wrapper
 | 
			
		||||
 | 
			
		||||
# NOTE: Threads WILL die with parent's destruction.
 | 
			
		||||
def daemon_threaded(fn):
 | 
			
		||||
    def wrapper(*args, **kwargs):
 | 
			
		||||
        threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
 | 
			
		||||
 | 
			
		||||
    return wrapper
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +27,7 @@ class GrepSearchMixin:
 | 
			
		||||
    def _run_grep_query(self, widget=None, eve=None):
 | 
			
		||||
        self._handle_grep_query(query=widget)
 | 
			
		||||
 | 
			
		||||
    # TODO: Merge this logic with nearly the exact same thing in file_search_mixin
 | 
			
		||||
    @daemon_threaded
 | 
			
		||||
    def _handle_grep_query(self, widget=None, eve=None, query=None):
 | 
			
		||||
        # NOTE: Freeze IPC consumption
 | 
			
		||||
@@ -33,19 +36,15 @@ class GrepSearchMixin:
 | 
			
		||||
 | 
			
		||||
        # NOTE: Kill the former process
 | 
			
		||||
        if self._grep_proc:
 | 
			
		||||
            if self._grep_proc.poll():
 | 
			
		||||
                self._grep_proc.send_signal(signal.SIGKILL)
 | 
			
		||||
                while self._grep_proc.poll():
 | 
			
		||||
                    pass
 | 
			
		||||
            if self._grep_proc.poll() == None:
 | 
			
		||||
                self._grep_proc.terminate()
 | 
			
		||||
                while self._grep_proc.poll() == None:
 | 
			
		||||
                    ...
 | 
			
		||||
 | 
			
		||||
            self._grep_proc = None
 | 
			
		||||
            else:
 | 
			
		||||
                self._grep_proc = None
 | 
			
		||||
 | 
			
		||||
        # NOTE: Clear children from ui and make sure ui thread redraws
 | 
			
		||||
        GLib.idle_add(self.clear_children, self._grep_list)
 | 
			
		||||
        while len(self._grep_list.get_children()) > 0:
 | 
			
		||||
            time.sleep(0.2)
 | 
			
		||||
        GLib.idle_add(self.reset_grep_box)
 | 
			
		||||
 | 
			
		||||
        # NOTE: If query create new process and do all new loop.
 | 
			
		||||
        self.pause_fifo_update = False
 | 
			
		||||
@@ -62,9 +61,6 @@ class GrepSearchMixin:
 | 
			
		||||
            self._grep_proc = subprocess.Popen(command, cwd=self.path, stdin=None, stdout=None, stderr=None)
 | 
			
		||||
 | 
			
		||||
    def _load_grep_ui(self, data):
 | 
			
		||||
        if self.pause_fifo_update:
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if not data in ("", None):
 | 
			
		||||
            jdata = json.loads( data )
 | 
			
		||||
            jkeys = jdata.keys()
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase):
 | 
			
		||||
 | 
			
		||||
        self._search_dialog    = None
 | 
			
		||||
        self._active_path      = None
 | 
			
		||||
        self.file_list_parent  = None
 | 
			
		||||
        self.grep_list_parent  = None
 | 
			
		||||
        self._file_list        = None
 | 
			
		||||
        self._grep_list        = None
 | 
			
		||||
        self._grep_proc        = None
 | 
			
		||||
@@ -72,10 +74,11 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase):
 | 
			
		||||
        self._builder.connect_signals(handlers)
 | 
			
		||||
 | 
			
		||||
        self._search_dialog = self._builder.get_object("search_dialog")
 | 
			
		||||
        self._grep_list     = self._builder.get_object("grep_list")
 | 
			
		||||
        self._file_list     = self._builder.get_object("file_list")
 | 
			
		||||
        self.fsearch        = self._builder.get_object("fsearch")
 | 
			
		||||
 | 
			
		||||
        self.grep_list_parent = self._builder.get_object("grep_list_parent")
 | 
			
		||||
        self.file_list_parent = self._builder.get_object("file_list_parent")
 | 
			
		||||
 | 
			
		||||
        self._event_system.subscribe("update-file-ui", self._load_file_ui)
 | 
			
		||||
        self._event_system.subscribe("update-grep-ui", self._load_grep_ui)
 | 
			
		||||
 | 
			
		||||
@@ -92,9 +95,29 @@ class Plugin(IPCServer, FileSearchMixin, GrepSearchMixin, PluginBase):
 | 
			
		||||
        response            = self._search_dialog.run()
 | 
			
		||||
        self._search_dialog.hide()
 | 
			
		||||
 | 
			
		||||
    # TODO: Merge the below methods into some unified logic
 | 
			
		||||
    def reset_grep_box(self) -> None:
 | 
			
		||||
        try:
 | 
			
		||||
            child = self.grep_list_parent.get_children()[0]
 | 
			
		||||
            self._grep_list = None
 | 
			
		||||
            self.grep_list_parent.remove(child)
 | 
			
		||||
        except Exception:
 | 
			
		||||
            ...
 | 
			
		||||
 | 
			
		||||
    def clear_children(self, widget: type) -> None:
 | 
			
		||||
        ''' Clear children of a gtk widget. '''
 | 
			
		||||
        for child in widget.get_children():
 | 
			
		||||
            widget.remove(child)
 | 
			
		||||
            time.sleep(0.01)
 | 
			
		||||
        self._grep_list = Gtk.Box()
 | 
			
		||||
        self._grep_list.set_orientation(Gtk.Orientation.VERTICAL)
 | 
			
		||||
        self.grep_list_parent.add(self._grep_list)
 | 
			
		||||
        self.grep_list_parent.show_all()
 | 
			
		||||
 | 
			
		||||
    def reset_file_list_box(self) -> None:
 | 
			
		||||
        try:
 | 
			
		||||
            child = self.file_list_parent.get_children()[0]
 | 
			
		||||
            self._file_list = None
 | 
			
		||||
            self.file_list_parent.remove(child)
 | 
			
		||||
        except Exception:
 | 
			
		||||
            ...
 | 
			
		||||
 | 
			
		||||
        self._file_list = Gtk.Box()
 | 
			
		||||
        self._file_list.set_orientation(Gtk.Orientation.VERTICAL)
 | 
			
		||||
        self.file_list_parent.add(self._file_list)
 | 
			
		||||
        self.file_list_parent.show_all()
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,10 @@
 | 
			
		||||
                <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="GtkSearchEntry" id="fsearch">
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
@@ -83,7 +87,28 @@
 | 
			
		||||
                        <property name="primary-icon-sensitive">False</property>
 | 
			
		||||
                        <property name="placeholder-text" translatable="yes">Search for file...</property>
 | 
			
		||||
                        <signal name="search-changed" handler="_run_find_file_query" swapped="no"/>
 | 
			
		||||
                    <signal name="stop-search" handler="_handle_find_file_query" 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="label">gtk-stop</property>
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
                        <property name="can-focus">True</property>
 | 
			
		||||
                        <property name="receives-default">True</property>
 | 
			
		||||
                        <property name="use-stock">True</property>
 | 
			
		||||
                        <signal name="released" handler="_handle_find_file_query" swapped="no"/>
 | 
			
		||||
                      </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>
 | 
			
		||||
@@ -103,7 +128,7 @@
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
                        <property name="can-focus">False</property>
 | 
			
		||||
                        <child>
 | 
			
		||||
                          <object class="GtkBox" id="file_list">
 | 
			
		||||
                          <object class="GtkBox" id="file_list_parent">
 | 
			
		||||
                            <property name="visible">True</property>
 | 
			
		||||
                            <property name="can-focus">False</property>
 | 
			
		||||
                            <property name="orientation">vertical</property>
 | 
			
		||||
@@ -140,6 +165,10 @@
 | 
			
		||||
                <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="GtkSearchEntry">
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
@@ -150,7 +179,28 @@
 | 
			
		||||
                        <property name="primary-icon-sensitive">False</property>
 | 
			
		||||
                        <property name="placeholder-text" translatable="yes">Query string in file...</property>
 | 
			
		||||
                        <signal name="search-changed" handler="_run_grep_query" swapped="no"/>
 | 
			
		||||
                    <signal name="stop-search" handler="_handle_grep_query" 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="label">gtk-stop</property>
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
                        <property name="can-focus">True</property>
 | 
			
		||||
                        <property name="receives-default">True</property>
 | 
			
		||||
                        <property name="use-stock">True</property>
 | 
			
		||||
                        <signal name="released" handler="_handle_grep_query" swapped="no"/>
 | 
			
		||||
                      </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>
 | 
			
		||||
@@ -170,12 +220,10 @@
 | 
			
		||||
                        <property name="visible">True</property>
 | 
			
		||||
                        <property name="can-focus">False</property>
 | 
			
		||||
                        <child>
 | 
			
		||||
                          <object class="GtkBox" id="grep_list">
 | 
			
		||||
                          <object class="GtkBox" id="grep_list_parent">
 | 
			
		||||
                            <property name="visible">True</property>
 | 
			
		||||
                            <property name="can-focus">False</property>
 | 
			
		||||
                            <property name="orientation">vertical</property>
 | 
			
		||||
                            <property name="spacing">5</property>
 | 
			
		||||
                            <property name="baseline-position">top</property>
 | 
			
		||||
                            <child>
 | 
			
		||||
                              <placeholder/>
 | 
			
		||||
                            </child>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python imports
 | 
			
		||||
import os, traceback, argparse, threading, json, base64, time
 | 
			
		||||
import os, traceback, argparse, threading, json, base64, time, pickle
 | 
			
		||||
from setproctitle import setproctitle
 | 
			
		||||
from multiprocessing.connection import Client
 | 
			
		||||
 | 
			
		||||
@@ -37,17 +37,16 @@ def send_ipc_message(message) -> None:
 | 
			
		||||
        conn.send(message)
 | 
			
		||||
        conn.close()
 | 
			
		||||
 | 
			
		||||
    time.sleep(0.05)
 | 
			
		||||
    # NOTE: Kinda important as this prevents overloading the UI thread
 | 
			
		||||
    time.sleep(0.04)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def file_search(path, query):
 | 
			
		||||
    try:
 | 
			
		||||
        for file in os.listdir(path):
 | 
			
		||||
            target = os.path.join(path, file)
 | 
			
		||||
            if os.path.isdir(target):
 | 
			
		||||
                file_search(target, query)
 | 
			
		||||
            else:
 | 
			
		||||
        for _path, _dir, _files in os.walk(path, topdown = True):
 | 
			
		||||
             for file in _files:
 | 
			
		||||
                 if query in file.lower():
 | 
			
		||||
                     target = os.path.join(_path, file)
 | 
			
		||||
                     data = f"SEARCH|{json.dumps([target, file])}"
 | 
			
		||||
                     send_ipc_message(data)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
@@ -59,8 +58,9 @@ def _search_for_string(file, query):
 | 
			
		||||
    grep_result_set = {}
 | 
			
		||||
    padding = 15
 | 
			
		||||
    with open(file, 'r') as fp:
 | 
			
		||||
        # NOTE: I know there's an issue if there's a very large file with content all on one line will lower and dupe it.
 | 
			
		||||
        #       And, yes, it will only return one instance from the file.
 | 
			
		||||
        # NOTE: I know there's an issue if there's a very large file with content
 | 
			
		||||
        #       all on one line will lower and dupe it. And, yes, it will only
 | 
			
		||||
        #       return one instance from the file.
 | 
			
		||||
        for i, raw in enumerate(fp):
 | 
			
		||||
            line   = None
 | 
			
		||||
            llower = raw.lower()
 | 
			
		||||
@@ -87,11 +87,11 @@ def _search_for_string(file, query):
 | 
			
		||||
        data = f"GREP|{json.dumps(grep_result_set)}"
 | 
			
		||||
        send_ipc_message(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@daemon_threaded
 | 
			
		||||
def _search_for_string_threaded(file, query):
 | 
			
		||||
    _search_for_string(file, query)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def grep_search(path, query):
 | 
			
		||||
    try:
 | 
			
		||||
        for file in os.listdir(path):
 | 
			
		||||
@@ -101,7 +101,7 @@ def grep_search(path, query):
 | 
			
		||||
            else:
 | 
			
		||||
                if target.lower().endswith(filter):
 | 
			
		||||
                    size = os.path.getsize(target)
 | 
			
		||||
                    if size < 5000:
 | 
			
		||||
                    if not size > 5000:
 | 
			
		||||
                        _search_for_string(target, query)
 | 
			
		||||
                    else:
 | 
			
		||||
                        _search_for_string_threaded(target, query)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user