Skip to content

Commit

Permalink
WIP: Find Files
Browse files Browse the repository at this point in the history
  • Loading branch information
MHendricks committed Mar 8, 2024
1 parent 7047908 commit abac596
Show file tree
Hide file tree
Showing 4 changed files with 352 additions and 2 deletions.
170 changes: 170 additions & 0 deletions preditor/gui/find_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
from __future__ import absolute_import, print_function

from collections import deque

from Qt.QtCore import Qt
from Qt.QtWidgets import QApplication, QShortcut, QWidget

from ..gui import loadUi


class FindFiles(QWidget):
def __init__(self, parent=None, managers=None, console=None):
super(FindFiles, self).__init__(parent=parent)
if managers is None:
managers = []
self.managers = managers
self.console = console

loadUi(__file__, self)

self.uiCloseSCT = QShortcut(
Qt.Key_Escape, self, context=Qt.WidgetWithChildrenShortcut
)
self.uiCloseSCT.activated.connect(self.hide)

def activate(self):
"""Called to make this widget ready for the user to interact with."""
self.show()
self.uiFindTXT.setFocus()

def insert_found_text(self, found_text, href, tool_tip):
cursor = self.console.textCursor()
# Insert hyperlink
fmt = cursor.charFormat()
fmt.setAnchor(True)
fmt.setAnchorHref(href)
fmt.setFontUnderline(True)
fmt.setToolTip(tool_tip)
cursor.insertText(found_text, fmt)
# Show the updated text output
QApplication.instance().processEvents()

def insert_text(self, text):
cursor = self.console.textCursor()
fmt = cursor.charFormat()
fmt.setAnchor(False)
fmt.setAnchorHref('')
fmt.setFontUnderline(False)
fmt.setToolTip('')
cursor.insertText(text, fmt)
# Show the updated text output
QApplication.instance().processEvents()

def indicate_results(
self,
line,
line_num,
find_text="undefined",
path="undefined",
workbox_id="undefined",
fmt="",
):
href = ', {}, {}'.format(workbox_id, line_num)
tool_tip = "Open {} at line number {}".format(path, line_num)
find_len = len(find_text)

start = 0
line = fmt.format(
num=line_num, split=" " if line.find(find_text) == -1 else ":", line=line
)
end = line.find(find_text)
count = 0
while end != -1:
# insert prefix text
self.insert_text(line[start:end])
# insert indicated text preserving case
self.insert_found_text(line[end : end + find_len], href, tool_tip)
start = end + find_len
end = line.find(find_text, start)
count += 1
if count > 10:
print('break', start, end)
break
if end < find_len:
self.insert_text(line[start:])

def print_lines(self, start, *lines, info=None):
if info is None:
info = {}
info.setdefault("fmt", " {num: 4d}{split} {line}")

# If start is negative, set it to zero
start = max(0, start)
for i, line in enumerate(lines):
# line = fmt.format(num=start + i, line=line)
# print(line)
self.indicate_results(line + "\n", start + i, **info)

def search_file_simple(self, editor, path, workbox_id):
# print('search_file_simple', path)
context = self.uiContextSPN.value()
find_text = self.uiFindTXT.text()
# Ensure the editor text is loaded
editor.__show__()
raw_lines = editor.__text__().splitlines()
# Add enough padding to cover the number of lines in the file
padding = len(str(len(raw_lines)))
fmt = " {{num: >{}}}{{split}} {{line}}".format(padding)

# https://stackoverflow.com/a/52009859
pre_history = deque(maxlen=context)
post_history = None
post_line = None
first = True
for i, line in enumerate(raw_lines):
# Lines are 1 based indexes
i += 1
info = dict(find_text=find_text, fmt=fmt, path=path, workbox_id=workbox_id)
if find_text in line:
ii = i - context
if first:
# Print the filename on the first find
print("# File: {}".format(path))
first = False
else:
print(
" {dot: >{padding}} ".format(
dot='.' * len(str(ii)), padding=padding
)
)
self.print_lines(ii, *pre_history, line, info=info)
# print(" xxx:", *pre_history, line, sep='')
# Clear history so if two errors seen in close proximity, we don't
# echo some lines twice
pre_history.clear()
# Start recording the post context
post_history = deque(maxlen=context)
post_line = i + 1
else:
# When deque reaches 25 lines, will automatically evict oldest
pre_history.append(line)
# Add the line to the post history after we find a result.
if post_history is not None:
post_history.append(line)
# Once we exceed context without finding another result,
# print the post text and stop tracking post_history
if len(post_history) >= context:
self.print_lines(post_line, *post_history, info=info)
post_history = None
post_line = None

if post_history:
print('# --------')
self.print_lines(post_line, *post_history, info=info)

def find(self):
find_text = self.uiFindTXT.text()
print("Find:", find_text)

for manager in self.managers:
for (
editor,
group_name,
tab_name,
group_index,
tab_index,
) in manager.all_widgets():
path = "/".join((group_name, tab_name))
workbox_id = '{},{}'.format(group_index, tab_index)
self.search_file_simple(editor, path, workbox_id)
10 changes: 10 additions & 0 deletions preditor/gui/loggerwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ def __init__(self, parent, name=None, run_workbox=False, standalone=False):
)
self.uiConsoleTOOLBAR.insertSeparator(self.uiRunSelectedACT)

# Configure Find in Workboxes
self.uiFindInWorkboxesWGT.hide()
self.uiFindInWorkboxesWGT.managers.append(self.uiWorkboxTAB)
self.uiFindInWorkboxesWGT.console = self.console()

# Initial configuration of the logToFile feature
self._logToFilePath = None
self._stds = None
Expand Down Expand Up @@ -1023,6 +1028,11 @@ def showEvent(self, event):
def show_workbox_options(self):
self.uiWorkboxSTACK.setCurrentIndex(WorkboxPages.Options)

@Slot()
def show_find_in_workboxes(self):
"""Ensure the find workboxes widget is visible and has focus."""
self.uiFindInWorkboxesWGT.activate()

@Slot()
def show_focus_name(self):
model = GroupTabListItemModel(manager=self.uiWorkboxTAB)
Expand Down
134 changes: 134 additions & 0 deletions preditor/gui/ui/find_files.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>uiFindFilesWGT</class>
<widget class="QWidget" name="uiFindFilesWGT">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>636</width>
<height>41</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<widget class="QLabel" name="uiFindLBL">
<property name="text">
<string>Find:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<layout class="QHBoxLayout" name="uiFindOptionsLYT">
<item>
<widget class="QToolButton" name="uiRegexBTN">
<property name="toolTip">
<string>Regex</string>
</property>
<property name="text">
<string>Regex</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="uiCaseSensitiveBTN">
<property name="toolTip">
<string>Case Sensitive</string>
</property>
<property name="text">
<string>Case Sensitive</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="uiContextSPN">
<property name="toolTip">
<string>Context Lines</string>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::PlusMinus</enum>
</property>
<property name="value">
<number>2</number>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="uiFindTXT"/>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="uiFindBTN">
<property name="text">
<string>Find</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QToolButton" name="uiCloseBTN">
<property name="text">
<string>x</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>uiFindBTN</sender>
<signal>released()</signal>
<receiver>uiFindFilesWGT</receiver>
<slot>find()</slot>
<hints>
<hint type="sourcelabel">
<x>601</x>
<y>31</y>
</hint>
<hint type="destinationlabel">
<x>421</x>
<y>29</y>
</hint>
</hints>
</connection>
<connection>
<sender>uiFindTXT</sender>
<signal>returnPressed()</signal>
<receiver>uiFindFilesWGT</receiver>
<slot>find()</slot>
<hints>
<hint type="sourcelabel">
<x>488</x>
<y>23</y>
</hint>
<hint type="destinationlabel">
<x>501</x>
<y>65</y>
</hint>
</hints>
</connection>
<connection>
<sender>uiCloseBTN</sender>
<signal>released()</signal>
<receiver>uiFindFilesWGT</receiver>
<slot>hide()</slot>
<hints>
<hint type="sourcelabel">
<x>620</x>
<y>19</y>
</hint>
<hint type="destinationlabel">
<x>676</x>
<y>24</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>find()</slot>
</slots>
</ui>
Loading

0 comments on commit abac596

Please sign in to comment.