search results fixed

This commit is contained in:
rdavidek 2026-01-21 18:31:32 +01:00
parent 9b6b309bfe
commit 6854693492
3 changed files with 293 additions and 181 deletions

View File

@ -7,7 +7,6 @@ import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.*;
@ -493,57 +492,57 @@ public class FileOperations {
}
/**
* Search files by pattern
* Search files by filename pattern and/or content text.
* If both are provided, both must match.
*/
public static void search(File directory, String pattern, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
if (pattern == null) return;
// Prepare a compiled regex if the pattern contains wildcards to avoid recompiling per-file
public static void search(File directory, String filenamePattern, String contentText, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
Pattern filenameRegex = null;
if (pattern.contains("*") || pattern.contains("?")) {
String regex = pattern
String filenameLower = null;
if (filenamePattern != null && !filenamePattern.isEmpty()) {
filenameLower = filenamePattern.toLowerCase();
if (filenamePattern.contains("*") || filenamePattern.contains("?")) {
String regex = filenamePattern
.replace(".", "\\.")
.replace("*", ".*")
.replace("?", ".");
filenameRegex = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
}
searchRecursive(directory.toPath(), pattern.toLowerCase(), filenameRegex, recursive, searchArchives, callback);
}
/**
* Search file contents for a text fragment (case-insensitive).
* Calls callback.onFileFound(file) when a file contains the text.
*/
public static void searchContents(File directory, String text, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
if (text == null) return;
// Precompile a case-insensitive pattern for content search to avoid per-line lowercasing
Pattern contentPattern = Pattern.compile(Pattern.quote(text), Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
searchContentsRecursive(directory.toPath(), contentPattern, recursive, searchArchives, callback);
Pattern contentPattern = null;
if (contentText != null && !contentText.isEmpty()) {
contentPattern = Pattern.compile(Pattern.quote(contentText), Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
}
private static void searchRecursive(Path directory, String patternLower, Pattern filenameRegex, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
searchRecursive(directory.toPath(), filenameLower, filenameRegex, contentPattern, recursive, searchArchives, callback);
}
private static void searchRecursive(Path directory, String patternLower, Pattern filenameRegex, Pattern contentPattern, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
if (recursive) {
searchRecursive(entry, patternLower, filenameRegex, recursive, searchArchives, callback);
searchRecursive(entry, patternLower, filenameRegex, contentPattern, recursive, searchArchives, callback);
}
} else {
File file = entry.toFile();
String fileName = file.getName();
String fileNameLower = fileName.toLowerCase();
boolean matched = false;
if (fileNameLower.contains(patternLower)) matched = true;
else if (filenameRegex != null) {
Matcher m = filenameRegex.matcher(fileName);
if (m.matches()) matched = true;
boolean nameMatched = true;
if (patternLower != null && !patternLower.isEmpty()) {
nameMatched = matchName(file.getName(), patternLower, filenameRegex);
}
if (matched) {
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
contentMatched = fileMatchesContent(entry, contentPattern);
}
if (nameMatched && contentMatched) {
callback.onFileFound(file, null);
}
// SEARCH IN ARCHIVES
if (searchArchives && isArchiveFile(file)) {
searchInArchive(file, fileNameLower, filenameRegex, callback);
searchInArchiveCombined(file, patternLower, filenameRegex, contentPattern, callback);
}
}
}
@ -552,39 +551,99 @@ public class FileOperations {
}
}
private static void searchContentsRecursive(Path directory, Pattern contentPattern, boolean recursive, boolean searchArchives, SearchCallback callback) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(directory)) {
for (Path entry : stream) {
if (Files.isDirectory(entry)) {
if (recursive) {
searchContentsRecursive(entry, contentPattern, recursive, searchArchives, callback);
private static boolean matchName(String name, String patternLower, Pattern filenameRegex) {
String nameLower = name.toLowerCase();
if (nameLower.contains(patternLower)) return true;
if (filenameRegex != null) {
return filenameRegex.matcher(name).matches();
}
} else {
File file = entry.toFile();
// Try reading file as text line-by-line and search for pattern (case-insensitive via compiled Pattern)
return false;
}
private static boolean fileMatchesContent(Path entry, Pattern contentPattern) {
try (BufferedReader br = Files.newBufferedReader(entry)) {
String line;
boolean found = false;
while ((line = br.readLine()) != null) {
if (contentPattern.matcher(line).find()) {
found = true;
break;
return true;
}
}
if (found) callback.onFileFound(file, null);
} catch (IOException ex) {
// Skip files that cannot be read as text
}
return false;
}
// SEARCH IN ARCHIVES CONTENTS
if (searchArchives && isArchiveFile(file)) {
searchContentsInArchive(file, contentPattern, callback);
/**
* Reads the content of a file from an archive.
*/
public static byte[] readFileFromArchive(File archive, String entryPath) throws IOException {
String name = archive.getName().toLowerCase();
try {
if (name.endsWith(".zip") || name.endsWith(".jar")) {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(archive))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (entry.getName().equals(entryPath) || (archive.getAbsolutePath() + File.separator + entry.getName()).equals(entryPath)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[24576];
int len;
while ((len = zis.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
}
}
}
} catch (AccessDeniedException e) {
// Ignore directories without access
} else if (name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".tar")) {
InputStream is = new FileInputStream(archive);
if (name.endsWith(".gz") || name.endsWith(".tgz")) {
is = new org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream(is);
}
try (org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(is)) {
org.apache.commons.compress.archivers.tar.TarArchiveEntry entry;
while ((entry = tais.getNextTarEntry()) != null) {
if (entry.getName().equals(entryPath) || (archive.getAbsolutePath() + File.separator + entry.getName()).equals(entryPath)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[24576];
int len;
while ((len = tais.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
}
}
}
} else if (name.endsWith(".7z")) {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (entry.getName().equals(entryPath) || (archive.getAbsolutePath() + File.separator + entry.getName()).equals(entryPath)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[24576];
int len;
while ((len = sevenZFile.read(buffer)) > 0) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
}
}
}
} else if (name.endsWith(".rar")) {
try (com.github.junrar.Archive rar = new com.github.junrar.Archive(archive)) {
for (com.github.junrar.rarfile.FileHeader fh : rar.getFileHeaders()) {
if (fh.getFileName().equals(entryPath) || (archive.getAbsolutePath() + File.separator + fh.getFileName()).equals(entryPath)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
rar.extractFile(fh, baos);
return baos.toByteArray();
}
}
}
}
} catch (Exception e) {
throw new IOException("Failed to read from archive: " + e.getMessage(), e);
}
throw new IOException("Entry not found in archive: " + entryPath);
}
private static boolean isArchiveFile(File f) {
@ -593,18 +652,28 @@ public class FileOperations {
return n.endsWith(".zip") || n.endsWith(".jar") || n.endsWith(".tar") || n.endsWith(".tar.gz") || n.endsWith(".tgz") || n.endsWith(".7z") || n.endsWith(".rar");
}
private static void searchInArchive(File archive, String patternLower, Pattern filenameRegex, SearchCallback callback) {
private static void searchInArchiveCombined(File archive, String patternLower, Pattern filenameRegex, Pattern contentPattern, SearchCallback callback) {
String name = archive.getName().toLowerCase();
try {
if (name.endsWith(".zip") || name.endsWith(".jar")) {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(archive))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (matchEntry(entry.getName(), patternLower, filenameRegex)) {
if (!entry.isDirectory()) {
boolean nameMatched = true;
if (patternLower != null && !patternLower.isEmpty()) {
nameMatched = matchEntry(entry.getName(), patternLower, filenameRegex);
}
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
contentMatched = searchInStream(zis, contentPattern);
}
if (nameMatched && contentMatched) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
}
} else if (name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".tar")) {
InputStream is = new FileInputStream(archive);
if (name.endsWith(".gz") || name.endsWith(".tgz")) {
@ -613,64 +682,33 @@ public class FileOperations {
try (org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(is)) {
org.apache.commons.compress.archivers.tar.TarArchiveEntry entry;
while ((entry = tais.getNextTarEntry()) != null) {
if (matchEntry(entry.getName(), patternLower, filenameRegex)) {
if (!entry.isDirectory()) {
boolean nameMatched = true;
if (patternLower != null && !patternLower.isEmpty()) {
nameMatched = matchEntry(entry.getName(), patternLower, filenameRegex);
}
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
contentMatched = searchInStream(tais, contentPattern);
}
if (nameMatched && contentMatched) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
} else if (name.endsWith(".7z")) {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (matchEntry(entry.getName(), patternLower, filenameRegex)) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
} else if (name.endsWith(".rar")) {
try (com.github.junrar.Archive rar = new com.github.junrar.Archive(archive)) {
for (com.github.junrar.rarfile.FileHeader fh : rar.getFileHeaders()) {
if (matchEntry(fh.getFileName(), patternLower, filenameRegex)) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + fh.getFileName());
}
}
}
}
} catch (Exception ignore) {}
}
private static void searchContentsInArchive(File archive, Pattern contentPattern, SearchCallback callback) {
String name = archive.getName().toLowerCase();
try {
if (name.endsWith(".zip") || name.endsWith(".jar")) {
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(archive))) {
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
if (!entry.isDirectory() && searchInStream(zis, contentPattern)) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
} else if (name.endsWith(".tar.gz") || name.endsWith(".tgz") || name.endsWith(".tar")) {
InputStream is = new FileInputStream(archive);
if (name.endsWith(".gz") || name.endsWith(".tgz")) {
is = new org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream(is);
}
try (org.apache.commons.compress.archivers.tar.TarArchiveInputStream tais = new org.apache.commons.compress.archivers.tar.TarArchiveInputStream(is)) {
org.apache.commons.compress.archivers.tar.TarArchiveEntry entry;
while ((entry = tais.getNextTarEntry()) != null) {
if (!entry.isDirectory() && searchInStream(tais, contentPattern)) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
}
} else if (name.endsWith(".7z")) {
try (org.apache.commons.compress.archivers.sevenz.SevenZFile sevenZFile = new org.apache.commons.compress.archivers.sevenz.SevenZFile(archive)) {
org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null) {
if (!entry.isDirectory()) {
// SevenZFile.read(buffer) reads from current entry
if (searchInStream(new InputStream() {
boolean nameMatched = true;
if (patternLower != null && !patternLower.isEmpty()) {
nameMatched = matchEntry(entry.getName(), patternLower, filenameRegex);
}
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
contentMatched = searchInStream(new InputStream() {
@Override
public int read() throws IOException {
return sevenZFile.read();
@ -679,7 +717,9 @@ public class FileOperations {
public int read(byte[] b, int off, int len) throws IOException {
return sevenZFile.read(b, off, len);
}
}, contentPattern)) {
}, contentPattern);
}
if (nameMatched && contentMatched) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + entry.getName());
}
}
@ -689,9 +729,17 @@ public class FileOperations {
try (com.github.junrar.Archive rar = new com.github.junrar.Archive(archive)) {
for (com.github.junrar.rarfile.FileHeader fh : rar.getFileHeaders()) {
if (!fh.isDirectory()) {
boolean nameMatched = true;
if (patternLower != null && !patternLower.isEmpty()) {
nameMatched = matchEntry(fh.getFileName(), patternLower, filenameRegex);
}
boolean contentMatched = true;
if (nameMatched && contentPattern != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
rar.extractFile(fh, baos);
if (contentPattern.matcher(new String(baos.toByteArray())).find()) {
contentMatched = contentPattern.matcher(new String(baos.toByteArray())).find();
}
if (nameMatched && contentMatched) {
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + fh.getFileName());
}
}
@ -701,6 +749,7 @@ public class FileOperations {
} catch (Exception ignore) {}
}
private static boolean matchEntry(String entryName, String patternLower, Pattern filenameRegex) {
if (entryName == null) return false;
String nameShort = entryName;

View File

@ -19,6 +19,7 @@ public class FileEditor extends JDialog {
private JTextArea textArea;
private JScrollPane scrollPane;
private File file;
private String virtualPath;
private java.util.List<File> imageFiles = new java.util.ArrayList<>();
private int currentImageIndex = -1;
private AppConfig config;
@ -52,12 +53,17 @@ public class FileEditor extends JDialog {
private static String lastSearchValue = "";
public FileEditor(Window parent, File file, AppConfig config, boolean readOnly) {
super(parent, (readOnly ? "Prohlížeč - " : "Editor - ") + file.getName(), ModalityType.MODELESS);
this(parent, file, null, config, readOnly);
}
public FileEditor(Window parent, File file, String virtualPath, AppConfig config, boolean readOnly) {
super(parent, (readOnly ? "Prohlížeč - " : "Editor - ") + (virtualPath != null ? virtualPath.substring(virtualPath.lastIndexOf(File.separator) + 1) : file.getName()), ModalityType.MODELESS);
this.file = file;
this.virtualPath = virtualPath;
this.config = config;
this.readOnly = readOnly;
if (isImageFile(file)) {
if (isImageFile(file) && virtualPath == null) {
initImageList();
}
@ -809,6 +815,38 @@ public class FileEditor extends JDialog {
}
private void loadFile() {
if (virtualPath != null) {
try {
fileBytes = cz.kamma.kfmanager.service.FileOperations.readFileFromArchive(file, virtualPath);
boolean binary = isBinary(fileBytes);
if (binary && readOnly) {
hexMode = true;
buildHexViewText(0L);
textArea.setEditable(false);
textArea.setFont(new Font("Monospaced", Font.PLAIN, textArea.getFont().getSize()));
ensureHexControls();
if (hexControlPanel.getParent() == null) northPanel.add(hexControlPanel);
hexControlPanel.setVisible(true);
northPanel.revalidate();
} else if (hexMode) {
buildHexViewText(0L);
} else {
String content = new String(fileBytes, "UTF-8");
textArea.setText(content);
textArea.setCaretPosition(0);
}
if (undoManager != null) undoManager.discardAllEdits();
modified = false;
updateTitle();
updateStatus();
return;
} catch (IOException e) {
JOptionPane.showMessageDialog(this, "Chyba při čtení z archivu: " + e.getMessage(), "Chyba", JOptionPane.ERROR_MESSAGE);
dispose();
return;
}
}
if (isImageFile(file)) {
loadImage();
return;

View File

@ -204,16 +204,30 @@ public class SearchDialog extends JDialog {
}
});
// Enter pro otevření umístění
resultsTable.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "openLocation");
resultsTable.getActionMap().put("openLocation", new AbstractAction() {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
openSelectedFile();
}
});
// Enable/disable view/edit buttons depending on selection
resultsTable.getSelectionModel().addListSelectionListener(e -> {
int sel = resultsTable.getSelectedRow();
boolean ok = false;
boolean canEdit = false;
if (sel >= 0) {
FileItem it = tableModel.getResult(sel);
ok = it != null && !it.isDirectory() && !"..".equals(it.getName());
if (ok) {
boolean inArchive = it.getPath() != null && !it.getPath().equals(it.getFile().getAbsolutePath());
canEdit = !inArchive;
}
}
viewButton.setEnabled(ok);
editButton.setEnabled(ok);
editButton.setEnabled(canEdit);
});
JScrollPane scrollPane = new JScrollPane(resultsTable);
@ -262,6 +276,9 @@ public class SearchDialog extends JDialog {
bottomPanel.add(buttonPanel, BorderLayout.SOUTH);
add(bottomPanel, BorderLayout.SOUTH);
// Set search button as default so Enter starts search
getRootPane().setDefaultButton(searchButton);
// Require explicit Enter to start search when choosing from history.
// Bind Enter on the combo editor component so selecting an item from the
// popup does not automatically trigger search until user confirms.
@ -273,17 +290,16 @@ public class SearchDialog extends JDialog {
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
try {
// If the popup is visible, treat Enter as "confirm selection": fill editor and close popup
// If the popup is visible, treat Enter as "confirm selection" and proceed to search
if (patternCombo.isPopupVisible()) {
Object sel = patternCombo.getSelectedItem();
if (sel != null) {
patternCombo.getEditor().setItem(sel.toString());
}
patternCombo.hidePopup();
return; // do not start search yet
}
} catch (Exception ignore) {}
// Popup not visible -> actual confirm to start search
// Actual confirm to start search
performSearch();
}
});
@ -303,7 +319,6 @@ public class SearchDialog extends JDialog {
Object sel = contentPatternCombo.getSelectedItem();
if (sel != null) contentPatternCombo.getEditor().setItem(sel.toString());
contentPatternCombo.hidePopup();
return;
}
} catch (Exception ignore) {}
performSearch();
@ -446,62 +461,64 @@ public class SearchDialog extends JDialog {
final boolean isContentSearch = contentSearchCheckBox != null && contentSearchCheckBox.isSelected();
if (isContentSearch) {
if (contentPat.isEmpty()) {
if (namePat.isEmpty() && (!isContentSearch || contentPat.isEmpty())) {
JOptionPane.showMessageDialog(this,
"Zadejte hledaný text",
"Zadejte hledaný vzor nebo text",
"Chyba",
JOptionPane.WARNING_MESSAGE);
return;
}
} else {
if (namePat.isEmpty()) {
if (isContentSearch && contentPat.isEmpty()) {
JOptionPane.showMessageDialog(this,
"Zadejte hledaný vzor",
"Zadejte hledaný text pro vyhledávání v obsahu",
"Chyba",
JOptionPane.WARNING_MESSAGE);
return;
}
}
tableModel.clear();
searchButton.setEnabled(false);
searching = true;
// Persist the chosen pattern into the appropriate history (most-recent-first)
// Persist the chosen patterns into history
if (config != null) {
try {
if (isContentSearch) {
java.util.List<String> chist = new java.util.ArrayList<>(config.getContentSearchHistory());
chist.remove(contentPat);
chist.add(0, contentPat);
int max = 20;
while (chist.size() > max) chist.remove(chist.size() - 1);
config.saveContentSearchHistory(chist);
config.saveConfig();
// update content combo model
javax.swing.DefaultComboBoxModel<String> cm = (javax.swing.DefaultComboBoxModel<String>) contentPatternCombo.getModel();
cm.removeAllElements();
for (String s : chist) cm.addElement(s);
contentPatternCombo.setSelectedItem(contentPat);
} else {
if (!namePat.isEmpty()) {
java.util.List<String> hist = new java.util.ArrayList<>(config.getSearchHistory());
hist.remove(namePat);
hist.add(0, namePat);
int max = 20;
while (hist.size() > max) hist.remove(hist.size() - 1);
config.saveSearchHistory(hist);
config.saveConfig();
// update combo model
javax.swing.DefaultComboBoxModel<String> m = (javax.swing.DefaultComboBoxModel<String>) patternCombo.getModel();
m.removeAllElements();
for (String s : hist) m.addElement(s);
patternCombo.setSelectedItem(namePat);
}
if (isContentSearch && !contentPat.isEmpty()) {
java.util.List<String> chist = new java.util.ArrayList<>(config.getContentSearchHistory());
chist.remove(contentPat);
chist.add(0, contentPat);
int max = 20;
while (chist.size() > max) chist.remove(chist.size() - 1);
config.saveContentSearchHistory(chist);
// update content combo model
javax.swing.DefaultComboBoxModel<String> cm = (javax.swing.DefaultComboBoxModel<String>) contentPatternCombo.getModel();
cm.removeAllElements();
for (String s : chist) cm.addElement(s);
contentPatternCombo.setSelectedItem(contentPat);
}
config.saveConfig();
} catch (Exception ignore) {}
}
final String pattern = isContentSearch ? contentPat : namePat;
final String finalNamePat = namePat;
final String finalContentPat = isContentSearch ? contentPat : null;
final boolean searchArchives = archiveSearchCheckBox != null && archiveSearchCheckBox.isSelected();
// Reset and show status
@ -514,17 +531,10 @@ public class SearchDialog extends JDialog {
SwingWorker<Void, Object[]> worker = new SwingWorker<Void, Object[]>() {
@Override
protected Void doInBackground() throws Exception {
if (isContentSearch) {
FileOperations.searchContents(searchDirectory, pattern, recursiveCheckBox.isSelected(), searchArchives, (file, virtualPath) -> {
FileOperations.search(searchDirectory, finalNamePat, finalContentPat, recursiveCheckBox.isSelected(), searchArchives, (file, virtualPath) -> {
if (!searching) return;
publish(new Object[]{file, virtualPath});
});
} else {
FileOperations.search(searchDirectory, pattern, recursiveCheckBox.isSelected(), searchArchives, (file, virtualPath) -> {
if (!searching) return;
publish(new Object[]{file, virtualPath});
});
}
return null;
}
@ -613,11 +623,18 @@ public class SearchDialog extends JDialog {
if (item != null && !item.isDirectory() && !"..".equals(item.getName())) {
try {
Frame owner = (Frame) SwingUtilities.getWindowAncestor(this);
FileEditor viewer = new FileEditor(owner, item.getFile(), config, true);
String vPath = null;
if (item.getPath() != null && !item.getPath().equals(item.getFile().getAbsolutePath())) {
vPath = item.getPath();
}
FileEditor viewer = new FileEditor(owner, item.getFile(), vPath, config, true);
viewer.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosed(java.awt.event.WindowEvent e) {
SwingUtilities.invokeLater(() -> {
SearchDialog.this.toFront();
resultsTable.requestFocusInWindow();
});
}
});
viewer.setVisible(true);
@ -636,13 +653,21 @@ public class SearchDialog extends JDialog {
if (sel >= 0) {
FileItem item = tableModel.getResult(sel);
if (item != null && !item.isDirectory() && !"..".equals(item.getName())) {
boolean inArchive = item.getPath() != null && !item.getPath().equals(item.getFile().getAbsolutePath());
if (inArchive) {
JOptionPane.showMessageDialog(this, "Editace souborů přímo v archivu není podporována. Použijte 'Otevřít umístění' pro přístup k archivu.", "Informace", JOptionPane.INFORMATION_MESSAGE);
return;
}
try {
Frame owner = (Frame) SwingUtilities.getWindowAncestor(this);
FileEditor editor = new FileEditor(owner, item.getFile(), config, false);
editor.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosed(java.awt.event.WindowEvent e) {
SwingUtilities.invokeLater(() -> {
SearchDialog.this.toFront();
resultsTable.requestFocusInWindow();
});
}
});
editor.setVisible(true);