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/locales/de_DE/LC_MESSAGES/messages.mo b/locales/de_DE/LC_MESSAGES/messages.mo
index 917c4b8..8532273 100644
Binary files a/locales/de_DE/LC_MESSAGES/messages.mo and b/locales/de_DE/LC_MESSAGES/messages.mo differ
diff --git a/locales/de_DE/LC_MESSAGES/messages.po b/locales/de_DE/LC_MESSAGES/messages.po
index 5f01a04..06879f5 100644
--- a/locales/de_DE/LC_MESSAGES/messages.po
+++ b/locales/de_DE/LC_MESSAGES/messages.po
@@ -5,80 +5,104 @@
msgid ""
msgstr ""
"Project-Id-Version: RavenLog\n"
-"POT-Creation-Date: 2022-02-12 10:14+0100\n"
-"PO-Revision-Date: 2022-02-12 10:17+0100\n"
+"POT-Creation-Date: 2022-08-21 09:51+0200\n"
+"PO-Revision-Date: 2022-08-21 09:58+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: pygettext.py 1.5\n"
-"X-Generator: Poedit 2.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Generated-By: pygettext.py 1.5\n"
+"X-Generator: Poedit 3.0.1\n"
-#: src/mainwindow.py:39 src/plugins/krowlog/aboutdialog.py:23
+#: src/mainwindow.py:34 src/plugins/krowlog/aboutdialog.py:24
#: src/plugins/krowlogplugin.py:85
msgid "KrowLog"
msgstr "KrowLog"
-#: src/mainwindow.py:47 src/plugins/openfileplugin.py:29
+#: src/mainwindow.py:42 src/plugins/openfileplugin.py:30
msgid "Open &Recent"
msgstr "Zu&letzt geöffnete Dateien"
-#: src/mainwindow.py:66
+#: src/mainwindow.py:64
msgid "&File"
msgstr "&Datei"
-#: src/mainwindow.py:67
+#: src/mainwindow.py:65
msgid "&Settings"
msgstr "&Einstellungen"
-#: src/mainwindow.py:68
+#: src/mainwindow.py:66
msgid "&Window"
msgstr "&Fenster"
-#: src/mainwindow.py:69
+#: src/mainwindow.py:67
msgid "&Help"
msgstr "&Hilfe"
-#: src/mainwindow.py:101 src/ui/bigtext/bigtext.py:187
+#: src/mainwindow.py:99 src/ui/bigtext/bigtext.py:188
msgid "&Highlighter"
msgstr "&Hervorhebungen"
-#: src/mainwindow.py:108
+#: src/mainwindow.py:106
msgid "Highlight &Searches"
msgstr "&Suchtreffer Hervorheben"
-#: src/mainwindow.py:116
+#: src/mainwindow.py:114
msgid "Open Tab on Save As File"
msgstr "Öffne neues Tab wenn Selektion als neue Datei gespeichert wird"
-#: src/plugins/krowlog/aboutdialog.py:18
+#: src/plugins/findInFiles/findinfileswidget.py:37
+msgid "Focus on current file"
+msgstr "Auf aktuelle Datei fokussieren"
+
+#: src/plugins/findInFiles/findinfileswidget.py:40
+msgid "Folder:"
+msgstr "Ordner:"
+
+#: src/plugins/findInFiles/findinfileswidget.py:45
+msgid "Filter:"
+msgstr "Filter:"
+
+#: src/plugins/findInFiles/findinfileswidget.py:83
+msgid "Open Directory"
+msgstr "Ordner öffnen"
+
+#: src/plugins/findinfilesplugin.py:31
+msgid "&Find In Files"
+msgstr "In &Dateien Suchen"
+
+#: src/plugins/findinfilesplugin.py:37
+msgid "Find In Files"
+msgstr "In Dateien Suchen"
+
+#: src/plugins/krowlog/aboutdialog.py:19
msgid "About KrowLog"
msgstr "Über KrowLog"
-#: src/plugins/krowlog/aboutdialog.py:28
+#: src/plugins/krowlog/aboutdialog.py:29
msgid "Version: {0}"
msgstr "Version: {0}"
-#: src/plugins/krowlog/aboutdialog.py:43
+#: src/plugins/krowlog/aboutdialog.py:44
msgid "About"
msgstr "Über KrowLog"
-#: src/plugins/krowlog/aboutdialog.py:44
+#: src/plugins/krowlog/aboutdialog.py:45
msgid "License"
msgstr "Lizenz"
-#: src/plugins/krowlog/aboutdialog.py:57
+#: src/plugins/krowlog/aboutdialog.py:58
msgid "Log file viewer"
msgstr "Betrachter für Logdateien"
-#: src/plugins/krowlog/aboutdialog.py:58
+#: src/plugins/krowlog/aboutdialog.py:59
msgid "(c) 2022 Andreas Huber"
msgstr "(c) 2022 Andreas Huber"
-#: src/plugins/krowlog/aboutdialog.py:59
+#: src/plugins/krowlog/aboutdialog.py:60
msgid "License: LGPL v3"
msgstr "Lizenz: LGPL v3"
@@ -122,71 +146,75 @@ msgstr "&Über KrowLog"
msgid "E&xit"
msgstr "&Beenden"
-#: src/plugins/logfile/filterwidget.py:134
+#: src/plugins/logfile/filterwidget.py:137
msgid "Cancel"
msgstr "Abbrechen"
-#: src/plugins/logfile/filterwidget.py:138
+#: src/plugins/logfile/filterwidget.py:143
+msgid "save query"
+msgstr "suche speichern"
+
+#: src/plugins/logfile/filterwidget.py:148
msgid "ignore case"
msgstr "Groß-/Kleinschreibung ignorieren"
-#: src/plugins/logfile/filterwidget.py:142
+#: src/plugins/logfile/filterwidget.py:152
msgid "regex"
msgstr "RegExp"
-#: src/plugins/logfileplugin.py:25
+#: src/plugins/logfileplugin.py:26
msgid "File not found"
msgstr "Datei nicht gefunden"
-#: src/plugins/logfileplugin.py:26
+#: src/plugins/logfileplugin.py:27
msgid "'{0}' is not a file or cannot be opened"
msgstr "'{0}' ist keine Datei oder kann nicht geöffnet werden"
-#: src/plugins/notesplugin.py:25
-msgid "Add &Notes"
-msgstr "&Notizen Hinzufügen"
+#: src/plugins/notesplugin.py:24
+msgid "&Notes"
+msgstr "&Notizen"
-#: src/plugins/notesplugin.py:33
+#: src/plugins/notesplugin.py:32
msgid "Notes {0}"
msgstr "Notizen {0}"
-#: src/plugins/openfileplugin.py:24
+#: src/plugins/openfileplugin.py:25
msgid "&Open..."
msgstr "&Öffnen..."
-#: src/plugins/openfileplugin.py:45
+#: src/plugins/openfileplugin.py:46
msgid "Open File"
msgstr "Öffne Datei"
-#: src/ui/bigtext/bigtext.py:170
+#: src/ui/bigtext/bigtext.py:171
msgid "&Copy to Clipboard"
msgstr "In Zwischenablage &Kopieren"
-#: src/ui/bigtext/bigtext.py:176
+#: src/ui/bigtext/bigtext.py:177
msgid "Copy to &File"
msgstr "In &Datei Kopieren"
-#: src/ui/bigtext/bigtext.py:181
+#: src/ui/bigtext/bigtext.py:182
msgid "Select &All"
msgstr "&Alles Selektieren"
-#: src/ui/bigtext/bigtext.py:331
+#: src/ui/bigtext/bigtext.py:332
msgid "data selection"
msgstr "selektion"
-#: src/ui/bigtext/bigtext.py:332
+#: src/ui/bigtext/bigtext.py:333
msgid "You have selected {0} of data."
msgstr "Du hast {0} selektiert."
-#: src/ui/bigtext/bigtext.py:335
+#: src/ui/bigtext/bigtext.py:336
msgid "Copy {0} to Clipboard"
msgstr "Kopiere {0} in die Zwischenablage"
-#: src/ui/bigtext/bigtext.py:337
+#: src/ui/bigtext/bigtext.py:338
msgid "Write to File"
msgstr "Schreibe in Datei"
-#: src/ui/bigtext/bigtext.py:359
+#: src/ui/bigtext/bigtext.py:360
msgid "Save File"
msgstr "Speichere Datei"
diff --git a/locales/messages.pot b/locales/messages.pot
index e865184..ddc0bb6 100644
--- a/locales/messages.pot
+++ b/locales/messages.pot
@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2022-02-12 10:14+0100\n"
+"POT-Creation-Date: 2022-08-21 09:51+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -15,68 +15,92 @@ msgstr ""
"Generated-By: pygettext.py 1.5\n"
-#: src/mainwindow.py:39 src/plugins/krowlog/aboutdialog.py:23
+#: src/mainwindow.py:34 src/plugins/krowlog/aboutdialog.py:24
#: src/plugins/krowlogplugin.py:85
msgid "KrowLog"
msgstr ""
-#: src/mainwindow.py:47 src/plugins/openfileplugin.py:29
+#: src/mainwindow.py:42 src/plugins/openfileplugin.py:30
msgid "Open &Recent"
msgstr ""
-#: src/mainwindow.py:66
+#: src/mainwindow.py:64
msgid "&File"
msgstr ""
-#: src/mainwindow.py:67
+#: src/mainwindow.py:65
msgid "&Settings"
msgstr ""
-#: src/mainwindow.py:68
+#: src/mainwindow.py:66
msgid "&Window"
msgstr ""
-#: src/mainwindow.py:69
+#: src/mainwindow.py:67
msgid "&Help"
msgstr ""
-#: src/mainwindow.py:101 src/ui/bigtext/bigtext.py:187
+#: src/mainwindow.py:99 src/ui/bigtext/bigtext.py:188
msgid "&Highlighter"
msgstr ""
-#: src/mainwindow.py:108
+#: src/mainwindow.py:106
msgid "Highlight &Searches"
msgstr ""
-#: src/mainwindow.py:116
+#: src/mainwindow.py:114
msgid "Open Tab on Save As File"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:18
+#: src/plugins/findInFiles/findinfileswidget.py:37
+msgid "Focus on current file"
+msgstr ""
+
+#: src/plugins/findInFiles/findinfileswidget.py:40
+msgid "Folder:"
+msgstr ""
+
+#: src/plugins/findInFiles/findinfileswidget.py:45
+msgid "Filter:"
+msgstr ""
+
+#: src/plugins/findInFiles/findinfileswidget.py:83
+msgid "Open Directory"
+msgstr ""
+
+#: src/plugins/findinfilesplugin.py:31
+msgid "&Find In Files"
+msgstr ""
+
+#: src/plugins/findinfilesplugin.py:37
+msgid "Find In Files"
+msgstr ""
+
+#: src/plugins/krowlog/aboutdialog.py:19
msgid "About KrowLog"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:28
+#: src/plugins/krowlog/aboutdialog.py:29
msgid "Version: {0}"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:43
+#: src/plugins/krowlog/aboutdialog.py:44
msgid "About"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:44
+#: src/plugins/krowlog/aboutdialog.py:45
msgid "License"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:57
+#: src/plugins/krowlog/aboutdialog.py:58
msgid "Log file viewer"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:58
+#: src/plugins/krowlog/aboutdialog.py:59
msgid "(c) 2022 Andreas Huber"
msgstr ""
-#: src/plugins/krowlog/aboutdialog.py:59
+#: src/plugins/krowlog/aboutdialog.py:60
msgid "License: LGPL v3"
msgstr ""
@@ -116,71 +140,79 @@ msgstr ""
msgid "E&xit"
msgstr ""
-#: src/plugins/logfile/filterwidget.py:134
+#: src/plugins/logfile/filterwidget.py:137
msgid "Cancel"
msgstr ""
-#: src/plugins/logfile/filterwidget.py:138
+#: src/plugins/logfile/filterwidget.py:143
+msgid "save query"
+msgstr ""
+
+#: src/plugins/logfile/filterwidget.py:148
msgid "ignore case"
msgstr ""
-#: src/plugins/logfile/filterwidget.py:142
+#: src/plugins/logfile/filterwidget.py:152
msgid "regex"
msgstr ""
-#: src/plugins/logfileplugin.py:25
+#: src/plugins/logfileplugin.py:26
msgid "File not found"
msgstr ""
-#: src/plugins/logfileplugin.py:26
+#: src/plugins/logfileplugin.py:27
msgid "'{0}' is not a file or cannot be opened"
msgstr ""
-#: src/plugins/notesplugin.py:25
-msgid "Add &Notes"
+#: src/plugins/notesplugin.py:24
+msgid "&Notes"
msgstr ""
-#: src/plugins/notesplugin.py:33
+#: src/plugins/notesplugin.py:32
msgid "Notes {0}"
msgstr ""
-#: src/plugins/openfileplugin.py:24
+#: src/plugins/openfileplugin.py:25
msgid "&Open..."
msgstr ""
-#: src/plugins/openfileplugin.py:45
+#: src/plugins/openfileplugin.py:46
msgid "Open File"
msgstr ""
-#: src/ui/bigtext/bigtext.py:170
+#: src/plugins/timediffplugin.py:17
+msgid ""
+msgstr ""
+
+#: src/ui/bigtext/bigtext.py:171
msgid "&Copy to Clipboard"
msgstr ""
-#: src/ui/bigtext/bigtext.py:176
+#: src/ui/bigtext/bigtext.py:177
msgid "Copy to &File"
msgstr ""
-#: src/ui/bigtext/bigtext.py:181
+#: src/ui/bigtext/bigtext.py:182
msgid "Select &All"
msgstr ""
-#: src/ui/bigtext/bigtext.py:331
+#: src/ui/bigtext/bigtext.py:332
msgid "data selection"
msgstr ""
-#: src/ui/bigtext/bigtext.py:332
+#: src/ui/bigtext/bigtext.py:333
msgid "You have selected {0} of data."
msgstr ""
-#: src/ui/bigtext/bigtext.py:335
+#: src/ui/bigtext/bigtext.py:336
msgid "Copy {0} to Clipboard"
msgstr ""
-#: src/ui/bigtext/bigtext.py:337
+#: src/ui/bigtext/bigtext.py:338
msgid "Write to File"
msgstr ""
-#: src/ui/bigtext/bigtext.py:359
+#: src/ui/bigtext/bigtext.py:360
msgid "Save File"
msgstr ""
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/requirements.txt b/requirements.txt
index de4ef0d..1659223 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
-pip==22.1.2
+pip==22.2.2
PySide6==6.3.1
setuptools==62.1.0
-urllib3==1.26.9
+urllib3==1.26.11
watchdog==2.1.9
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..8805d13
--- /dev/null
+++ b/src/plugins/findInFiles/findinfileswidget.py
@@ -0,0 +1,119 @@
+import os
+import sys
+from pathlib import Path
+
+from PySide6.QtCore import QDir, QModelIndex
+from PySide6.QtGui import QIcon
+
+from src.pluginregistry import PluginRegistry
+from src.plugins.krowlog.Tab import Tab
+from PySide6.QtWidgets import QVBoxLayout, QLabel, QLineEdit, QPushButton, QFileDialog, QTreeView, \
+ QFileSystemModel
+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("folder"), "")
+ 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(self._settings.get_session("findInFiles", "filter", fallback="*.log"))
+ self._filter.textChanged.connect(self._filter_changed)
+ form.addRow(QLabel(_("Filter:")), self._filter)
+
+ self._model = QFileSystemModel()
+ self._model.setRootPath(self._base_dir.text())
+ self._model.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot | QDir.AllEntries)
+ self._model.setNameFilters([self._filter.text()])
+ self._model.setNameFilterDisables(False)
+ self._view = QTreeView()
+ self._view.setModel(self._model)
+ self._view.setRootIndex(self._model.index(self._base_dir.text()))
+ self._view.hideColumn(2) # hide type column
+ self._view.show()
+ self.layout.addWidget(self._view)
+
+ self._view.doubleClicked.connect(self._open_file)
+
+ # icons: /snap/gtk-common-themes/1534/share/icons/
+ # folder, document, text-css, text-xml, text-x-python
+ #
+
+ def _open_file(self, index: QModelIndex):
+
+ path = []
+ i = index
+ while i.isValid():
+ path.append(i.data())
+ i = i.parent()
+ path.reverse()
+ file = Path()
+ for s in path:
+ file = file / s
+
+ if file.is_file():
+ PluginRegistry.execute_single("open_file", f"{file}")
+
+ 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 _filter_changed(self, filter):
+ self._settings.set_session("findInFiles", "filter", filter)
+ self._model.setNameFilters([filter])
+
+ def _base_dir_changed(self, base_dir):
+ if os.path.isdir(base_dir):
+ self._settings.set_session("findInFiles", "folder", base_dir)
+ self._model.setRootPath(base_dir)
+ self._view.setRootIndex(self._model.index(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..914b18f
--- /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):
+ find_in_files = FindInFilesWidget(
+ "find_in_files",
+ _("Find In Files"),
+ self.settings
+ )
+ PluginRegistry.execute_single("add_dock", Qt.DockWidgetArea.LeftDockWidgetArea, find_in_files)
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/plugins/timediffplugin.py b/src/plugins/timediffplugin.py
index 1cab5de..a2d0795 100644
--- a/src/plugins/timediffplugin.py
+++ b/src/plugins/timediffplugin.py
@@ -14,7 +14,7 @@ class TimeDiffPlugin(PluginBase):
def __init__(self):
super(TimeDiffPlugin, self).__init__()
self.time_diff_state = False
- self.time_diff_action = RAction(_(""), lambda: self._toggle_time_diff(),
+ self.time_diff_action = RAction("", lambda: self._toggle_time_diff(),
icon_file="icons/ionicons/stopwatch-outline.svg", checkable=True)
self.time_diff_hook = TimeDiffPreProcessLinesHook()
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)