diff --git a/icons/ionicons/search-circle.svg b/icons/ionicons/search-circle.svg
new file mode 100644
index 0000000..e9e1a04
--- /dev/null
+++ b/icons/ionicons/search-circle.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/icons/ionicons/search-outline.svg b/icons/ionicons/search-outline.svg
new file mode 100644
index 0000000..eb09c6c
--- /dev/null
+++ b/icons/ionicons/search-outline.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/icons/ionicons/search-sharp.svg b/icons/ionicons/search-sharp.svg
new file mode 100644
index 0000000..3be92cc
--- /dev/null
+++ b/icons/ionicons/search-sharp.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/icons/myicons/target.svg b/icons/myicons/target.svg
new file mode 100644
index 0000000..9169f5b
--- /dev/null
+++ b/icons/myicons/target.svg
@@ -0,0 +1,13 @@
+
diff --git a/main.py b/main.py
index b3319a5..98338dc 100644
--- a/main.py
+++ b/main.py
@@ -55,6 +55,7 @@ if __name__ == "__main__":
PluginRegistry.load_plugin("LogFilePlugin")
PluginRegistry.load_plugin("NotesPlugin")
PluginRegistry.load_plugin("TimeDiffPlugin")
+ PluginRegistry.load_plugin("FindInFilesPlugin")
window = PluginRegistry.execute_single("create_main_window")
window.show()
diff --git a/src/plugins/domain/menucontribution.py b/src/plugins/domain/menucontribution.py
index 5496d12..7b4e8f2 100644
--- a/src/plugins/domain/menucontribution.py
+++ b/src/plugins/domain/menucontribution.py
@@ -33,18 +33,50 @@ def sort_menu_contributions(menu_contributions: [MenuContribution]) -> [MenuCont
result = []
items = _sort_by_action_id(menu_contributions[:])
- _recursive_half_order_adder(result, items)
-
- # add remaining items to the end (ordered by their action_id)
- # This resolves cycles.
- for item in items:
- result.append(item)
- return result
-
-
-def _recursive_half_order_adder(result: [MenuContribution], items: [MenuContribution]):
for item in items:
mc: MenuContribution = item
+ if not mc.after:
+ result.append(mc)
+ items.remove(mc)
+ result = result + _new_recursive(mc.action_id, items)
+
+ # _recursive_half_order_adder(result, items)
+
+ # add remaining items to the end (ordered by their action_id)
+ # This resolves cycles.
+ for item in items:
+ if result.count(item) == 0:
+ result.append(item)
+ return result
+
+
+def _new_recursive(current_action_id: str, items: [MenuContribution]) -> [MenuContribution]:
+ result = []
+ for item in items:
+
+ mc: MenuContribution = item
+ print("%s checking %s" % (current_action_id, mc.action_id))
+ if mc.after == current_action_id:
+ print("%s adding %s" % (current_action_id, mc.action_id))
+ result.append(mc)
+ result = result + _new_recursive(mc.action_id, items)
+
+ return result
+
+
+def _recursive_half_order_adder(result: [MenuContribution], items: [MenuContribution]):
+ print("%s -- %s" % ([mc.action_id for mc in result], [mc.action_id for mc in items]))
+ for item in items:
+ mc: MenuContribution = item
+ if mc.after:
+ index = 0
+ for r in result:
+ index = index + 1
+ mc_in_result: MenuContribution = r
+ if mc.after == mc_in_result.action_id:
+ result.insert(index, mc)
+ items.remove(mc)
+ _recursive_half_order_adder(result, items)
if not mc.after:
result.append(mc)
items.remove(mc)
diff --git a/src/plugins/domain/testmenucontribution.py b/src/plugins/domain/testmenucontribution.py
index ae1b2be..23b6cd7 100644
--- a/src/plugins/domain/testmenucontribution.py
+++ b/src/plugins/domain/testmenucontribution.py
@@ -40,6 +40,39 @@ class MyTestCase(unittest.TestCase):
ordered_ids = ordered_ids + a.action_id
self.assertEqual("ab", ordered_ids)
+ def test_sort_with_non_consecutive_action_ids(self):
+ items = [
+ MenuContribution("menuId", action_id="The", after=None),
+ MenuContribution("menuId", action_id="quick", after="The"),
+ MenuContribution("menuId", action_id="brown", after="quick"),
+ MenuContribution("menuId", action_id="fox", after="brown"),
+ MenuContribution("menuId", action_id="jumped", after="fox"),
+ ]
+ shuffle(items)
+
+ actual = sort_menu_contributions(items)
+ ordered_ids = ""
+ for a in actual:
+ ordered_ids = ordered_ids + a.action_id
+ self.assertEqual("Thequickbrownfoxjumped", ordered_ids)
+
+ def test_sort_with_multiple_equal_after_values(self):
+ items = [
+ MenuContribution("menuId", action_id="Tanja", after=None),
+ MenuContribution("menuId", action_id="jumps", after="Tanja"),
+ MenuContribution("menuId", action_id="over", after="Tanja"),
+ MenuContribution("menuId", action_id="the", after="Tanja"),
+ MenuContribution("menuId", action_id="yellow", after="Tanja"),
+ MenuContribution("menuId", action_id="Zebra", after=None),
+ ]
+ shuffle(items)
+
+ actual = sort_menu_contributions(items)
+ ordered_ids = ""
+ for a in actual:
+ ordered_ids = ordered_ids + a.action_id
+ self.assertEqual("TanjajumpsovertheyellowZebra", ordered_ids)
+
if __name__ == '__main__':
unittest.main()
diff --git a/src/plugins/findInFiles/__init__.py b/src/plugins/findInFiles/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/plugins/findInFiles/findinfileswidget.py b/src/plugins/findInFiles/findinfileswidget.py
new file mode 100644
index 0000000..a5f501e
--- /dev/null
+++ b/src/plugins/findInFiles/findinfileswidget.py
@@ -0,0 +1,86 @@
+import os
+import sys
+from pathlib import Path
+
+from PySide6.QtGui import QIcon
+
+from src.pluginregistry import PluginRegistry
+from src.plugins.krowlog.Tab import Tab
+from PySide6.QtWidgets import QTextEdit, QVBoxLayout, QLabel, QLineEdit, QPushButton, QFileDialog
+from src.i18n import _
+from src.settings.settings import Settings
+from src.ui.formgrid import FormGrid
+from src.ui.hbox import HBox
+
+
+class FindInFilesWidget(Tab):
+
+ def __init__(self, unique_id: str, title: str, settings: Settings):
+ super(FindInFilesWidget, self).__init__(unique_id, title)
+ self._settings = settings
+
+ self.layout = QVBoxLayout(self)
+ self.layout.setContentsMargins(0, 0, 0, 0)
+ form = FormGrid();
+ self.layout.addWidget(form)
+
+ self._base_dir = QLineEdit(self._initialFolder())
+ self._base_dir.textChanged.connect(self._base_dir_changed)
+
+ btn_select_base_dir = QPushButton(QIcon.fromTheme("document-open"), "")
+ btn_select_base_dir.pressed.connect(self._select_base_dir)
+
+ btn_base_dir_for_current_file = QPushButton(QIcon("icons/myicons/target.svg"), "")
+ btn_base_dir_for_current_file.setToolTip(_("Focus on current file"))
+ btn_base_dir_for_current_file.pressed.connect(self._select_btn_base_dir_for_current_file)
+
+ form.addRow(QLabel(_("Folder:")),
+ HBox(self._base_dir, btn_select_base_dir, btn_base_dir_for_current_file))
+
+ self._filter = QLineEdit("*.log")
+ form.addRow(QLabel(_("Filter:")), self._filter)
+
+ self._btn_search = QPushButton(QIcon("icons/ionicons/search-outline.svg"), _("Search"))
+ self._btn_search.pressed.connect(self._search)
+ self.layout.addWidget(self._btn_search)
+
+ self.layout.addWidget(QTextEdit())
+
+ def _search(self):
+ pass
+
+ def _select_base_dir(self):
+ dialog = QFileDialog()
+ selected_dir = dialog.getExistingDirectory(
+ caption=_("Open Directory"),
+ dir=self._base_dir.text()
+ )
+ if selected_dir:
+ self._base_dir.setText(selected_dir)
+
+ def _select_btn_base_dir_for_current_file(self):
+ dir = self._get_base_dir_for_current_file()
+ self._base_dir.setText(dir)
+
+ def _base_dir_changed(self, base_dir):
+ if os.path.isdir(base_dir):
+ self._settings.set_session("findInFiles", "folder", base_dir)
+
+ def _initialFolder(self) -> str:
+ folder = self._settings.get_session("findInFiles", "folder", fallback=None)
+ if folder is None or not os.path.isdir(folder):
+ folder = self._get_base_dir_for_current_file()
+
+ return folder
+
+ def _get_base_dir_for_current_file(self):
+ current_file = PluginRegistry.execute_single("current_file")
+ folder = os.path.dirname(current_file) if current_file else None
+
+ if not os.path.isdir(folder):
+ if sys.platform == 'win32' or sys.platform == 'cygwin':
+ folder = "C:\\"
+ else:
+ folder = os.path.join(Path.home())
+
+ return folder
diff --git a/src/plugins/findinfilesplugin.py b/src/plugins/findinfilesplugin.py
new file mode 100644
index 0000000..5642138
--- /dev/null
+++ b/src/plugins/findinfilesplugin.py
@@ -0,0 +1,40 @@
+from PySide6.QtCore import Qt
+
+from src.pluginbase import PluginBase
+from src.pluginregistry import PluginRegistry
+from src.plugins.domain.menucontribution import MenuContribution
+from src.plugins.domain.raction import RAction
+from src.plugins.findInFiles.findinfileswidget import FindInFilesWidget
+from src.plugins.notes.noteswidget import NotesWidget
+from src.i18n import _
+from src.settings.settings import Settings
+
+
+class FindInFilesPlugin(PluginBase):
+
+ def __init__(self):
+ super(FindInFilesPlugin, self).__init__()
+ self.settings = None
+
+ def set_settings(self, settings: Settings):
+ self.settings = settings
+ if not self.settings.session.has_section("findInFiles"):
+ self.settings.session.add_section("findInFiles")
+
+ def get_menu_contributions(self) -> [MenuContribution]:
+ return [
+ MenuContribution("window", action=self._add_find_in_files_tab_action(), action_id="add find in files tab",
+ after="add notes tab"),
+ ]
+
+ def _add_find_in_files_tab_action(self) -> RAction:
+ return RAction(_("&Find In Files"), self._add_notes_tab, shortcut='Ctrl+Shift+F',
+ icon_file="icons/ionicons/search-outline.svg")
+
+ def _add_notes_tab(self):
+ findInFiles = FindInFilesWidget(
+ "find_in_files",
+ _("Find In Files"),
+ self.settings
+ )
+ PluginRegistry.execute_single("add_dock", Qt.DockWidgetArea.LeftDockWidgetArea, findInFiles)
diff --git a/src/plugins/notesplugin.py b/src/plugins/notesplugin.py
index b0c8de3..111447a 100644
--- a/src/plugins/notesplugin.py
+++ b/src/plugins/notesplugin.py
@@ -21,7 +21,7 @@ class NotesPlugin(PluginBase):
]
def _add_notes_tab_action(self) -> RAction:
- open_file = RAction(_("Add &Notes"), self._add_notes_tab, shortcut='Ctrl+Shift+N',
+ open_file = RAction(_("&Notes"), self._add_notes_tab, shortcut='Ctrl+Shift+N',
icon_from_theme="filenew")
return open_file
diff --git a/src/ui/formgrid.py b/src/ui/formgrid.py
new file mode 100644
index 0000000..0289e2d
--- /dev/null
+++ b/src/ui/formgrid.py
@@ -0,0 +1,15 @@
+from PySide6.QtWidgets import QWidget, QGridLayout, QLabel
+
+
+class FormGrid(QWidget):
+ def __init__(self):
+ super(FormGrid, self).__init__()
+ self.layout = QGridLayout(self)
+ self.row = -1
+
+ def addRow(self, *widgets: QWidget):
+ self.row = self.row + 1
+ col = -1
+ for widget in widgets:
+ col = col + 1
+ self.layout.addWidget(widget, self.row, col)