UI fixes, added search support for archives
This commit is contained in:
parent
357aea509a
commit
2a516ab48c
@ -18,57 +18,63 @@ public class FileItem {
|
||||
private final boolean isDirectory;
|
||||
private final Icon icon;
|
||||
private boolean marked;
|
||||
|
||||
private String displayPath;
|
||||
|
||||
public FileItem(File file) {
|
||||
this(file, null);
|
||||
}
|
||||
|
||||
public FileItem(File file, String displayPath) {
|
||||
this.file = file;
|
||||
this.name = file.getName();
|
||||
this.size = file.length();
|
||||
this.modified = new Date(file.lastModified());
|
||||
this.isDirectory = file.isDirectory();
|
||||
this.marked = false;
|
||||
|
||||
this.displayPath = displayPath;
|
||||
|
||||
// Load icon from system
|
||||
this.icon = FileSystemView.getFileSystemView().getSystemIcon(file);
|
||||
}
|
||||
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getFormattedSize() {
|
||||
if (isDirectory) {
|
||||
return "<DIR>";
|
||||
}
|
||||
return formatSize(size);
|
||||
}
|
||||
|
||||
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
public String getFormattedDate() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm");
|
||||
return sdf.format(modified);
|
||||
}
|
||||
|
||||
|
||||
public Date getModified() {
|
||||
return modified;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDirectory() {
|
||||
return isDirectory;
|
||||
}
|
||||
|
||||
|
||||
public Icon getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
public String getPath() {
|
||||
return file.getAbsolutePath();
|
||||
return displayPath != null ? displayPath : file.getAbsolutePath();
|
||||
}
|
||||
|
||||
public boolean isMarked() {
|
||||
|
||||
@ -238,7 +238,7 @@ public class FileOperations {
|
||||
/**
|
||||
* Search files by pattern
|
||||
*/
|
||||
public static void search(File directory, String pattern, boolean recursive, SearchCallback callback) throws IOException {
|
||||
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
|
||||
Pattern filenameRegex = null;
|
||||
@ -249,29 +249,30 @@ public class FileOperations {
|
||||
.replace("?", ".");
|
||||
filenameRegex = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
|
||||
}
|
||||
searchRecursive(directory.toPath(), pattern.toLowerCase(), filenameRegex, recursive, callback);
|
||||
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, SearchCallback callback) throws IOException {
|
||||
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, callback);
|
||||
searchContentsRecursive(directory.toPath(), contentPattern, recursive, searchArchives, callback);
|
||||
}
|
||||
|
||||
private static void searchRecursive(Path directory, String patternLower, Pattern filenameRegex, boolean recursive, SearchCallback callback) throws IOException {
|
||||
private static void searchRecursive(Path directory, String patternLower, Pattern filenameRegex, 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, callback);
|
||||
searchRecursive(entry, patternLower, filenameRegex, recursive, searchArchives, callback);
|
||||
}
|
||||
} else {
|
||||
String fileName = entry.getFileName().toString();
|
||||
File file = entry.toFile();
|
||||
String fileName = file.getName();
|
||||
String fileNameLower = fileName.toLowerCase();
|
||||
boolean matched = false;
|
||||
if (fileNameLower.contains(patternLower)) matched = true;
|
||||
@ -280,7 +281,12 @@ public class FileOperations {
|
||||
if (m.matches()) matched = true;
|
||||
}
|
||||
if (matched) {
|
||||
callback.onFileFound(entry.toFile());
|
||||
callback.onFileFound(file, null);
|
||||
}
|
||||
|
||||
// SEARCH IN ARCHIVES
|
||||
if (searchArchives && isArchiveFile(file)) {
|
||||
searchInArchive(file, fileNameLower, filenameRegex, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -289,14 +295,15 @@ public class FileOperations {
|
||||
}
|
||||
}
|
||||
|
||||
private static void searchContentsRecursive(Path directory, Pattern contentPattern, boolean recursive, SearchCallback callback) throws IOException {
|
||||
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, callback);
|
||||
searchContentsRecursive(entry, contentPattern, recursive, searchArchives, callback);
|
||||
}
|
||||
} else {
|
||||
File file = entry.toFile();
|
||||
// Try reading file as text line-by-line and search for pattern (case-insensitive via compiled Pattern)
|
||||
try (BufferedReader br = Files.newBufferedReader(entry)) {
|
||||
String line;
|
||||
@ -307,16 +314,160 @@ public class FileOperations {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) callback.onFileFound(entry.toFile());
|
||||
if (found) callback.onFileFound(file, null);
|
||||
} catch (IOException ex) {
|
||||
// Skip files that cannot be read as text
|
||||
}
|
||||
|
||||
// SEARCH IN ARCHIVES CONTENTS
|
||||
if (searchArchives && isArchiveFile(file)) {
|
||||
searchContentsInArchive(file, contentPattern, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (AccessDeniedException e) {
|
||||
// Ignore directories without access
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isArchiveFile(File f) {
|
||||
if (f == null) return false;
|
||||
String n = f.getName().toLowerCase();
|
||||
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) {
|
||||
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)) {
|
||||
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 (matchEntry(entry.getName(), patternLower, filenameRegex)) {
|
||||
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() {
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return sevenZFile.read();
|
||||
}
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return sevenZFile.read(b, off, len);
|
||||
}
|
||||
}, contentPattern)) {
|
||||
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 (!fh.isDirectory()) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
rar.extractFile(fh, baos);
|
||||
if (contentPattern.matcher(new String(baos.toByteArray())).find()) {
|
||||
callback.onFileFound(archive, archive.getAbsolutePath() + File.separator + fh.getFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
private static boolean matchEntry(String entryName, String patternLower, Pattern filenameRegex) {
|
||||
if (entryName == null) return false;
|
||||
String nameShort = entryName;
|
||||
int lastSlash = entryName.lastIndexOf('/');
|
||||
if (lastSlash != -1) nameShort = entryName.substring(lastSlash + 1);
|
||||
|
||||
String nameLower = nameShort.toLowerCase();
|
||||
if (nameLower.contains(patternLower)) return true;
|
||||
if (filenameRegex != null && filenameRegex.matcher(nameShort).matches()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean searchInStream(InputStream is, Pattern contentPattern) {
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(is));
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (contentPattern.matcher(line).find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip files/directories into a target zip file
|
||||
@ -431,6 +582,6 @@ public class FileOperations {
|
||||
* Callback for search
|
||||
*/
|
||||
public interface SearchCallback {
|
||||
void onFileFound(File file);
|
||||
void onFileFound(File file, String virtualPath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,17 +283,44 @@ public class MainWindow extends JFrame {
|
||||
JTextField tf = (JTextField) editorComp;
|
||||
tf.setFocusTraversalKeysEnabled(false);
|
||||
tf.addActionListener(e -> executeCommand(tf.getText()));
|
||||
|
||||
// Enable standard clipboard operations (Cut, Copy, Paste) even if not focused initially
|
||||
tf.getComponentPopupMenu(); // Ensure it has a menu or at least default actions works
|
||||
|
||||
// Context menu with Clipboard operations
|
||||
JPopupMenu clipboardMenu = new JPopupMenu();
|
||||
Action cutAction = new javax.swing.text.DefaultEditorKit.CutAction();
|
||||
cutAction.putValue(Action.NAME, "Cut");
|
||||
clipboardMenu.add(cutAction);
|
||||
|
||||
Action copyAction = new javax.swing.text.DefaultEditorKit.CopyAction();
|
||||
copyAction.putValue(Action.NAME, "Copy");
|
||||
clipboardMenu.add(copyAction);
|
||||
|
||||
Action pasteAction = new javax.swing.text.DefaultEditorKit.PasteAction();
|
||||
pasteAction.putValue(Action.NAME, "Paste");
|
||||
clipboardMenu.add(pasteAction);
|
||||
|
||||
clipboardMenu.addSeparator();
|
||||
|
||||
Action selectAllAction = new AbstractAction("Select All") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tf.selectAll();
|
||||
}
|
||||
};
|
||||
clipboardMenu.add(selectAllAction);
|
||||
|
||||
tf.setComponentPopupMenu(clipboardMenu);
|
||||
|
||||
// Let the panels catch focus back if user presses ESC or TAB in command line
|
||||
tf.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
if (!tf.getText().isEmpty()) {
|
||||
tf.setText("");
|
||||
if (activePanel != null && activePanel.getFileTable() != null) {
|
||||
activePanel.getFileTable().requestFocusInWindow();
|
||||
}
|
||||
tf.setText("");
|
||||
if (activePanel != null && activePanel.getFileTable() != null) {
|
||||
activePanel.getFileTable().requestFocusInWindow();
|
||||
}
|
||||
e.consume();
|
||||
} else if (e.getKeyCode() == KeyEvent.VK_TAB) {
|
||||
@ -715,6 +742,24 @@ public class MainWindow extends JFrame {
|
||||
updateComponentBackground(getContentPane(), bg);
|
||||
if (leftPanel != null) leftPanel.applyBackgroundColor(bg);
|
||||
if (rightPanel != null) rightPanel.applyBackgroundColor(bg);
|
||||
|
||||
// Update command line colors
|
||||
if (commandLine != null) {
|
||||
Component ed = commandLine.getEditor().getEditorComponent();
|
||||
if (ed instanceof JTextField) {
|
||||
JTextField tf = (JTextField) ed;
|
||||
tf.setBackground(bg);
|
||||
boolean dark = isDark(bg);
|
||||
tf.setForeground(dark ? Color.WHITE : Color.BLACK);
|
||||
Color selColor = config.getSelectionColor();
|
||||
if (selColor != null) {
|
||||
tf.setSelectionColor(selColor);
|
||||
tf.setCaretColor(selColor);
|
||||
} else {
|
||||
tf.setCaretColor(dark ? Color.WHITE : Color.BLACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -722,6 +767,18 @@ public class MainWindow extends JFrame {
|
||||
if (sel != null) {
|
||||
if (leftPanel != null) leftPanel.applySelectionColor(sel);
|
||||
if (rightPanel != null) rightPanel.applySelectionColor(sel);
|
||||
|
||||
// Apply selection color to command line editor for cursor and selection
|
||||
if (commandLine != null) {
|
||||
Component ed = commandLine.getEditor().getEditorComponent();
|
||||
if (ed instanceof JTextField) {
|
||||
JTextField tf = (JTextField) ed;
|
||||
tf.setSelectionColor(sel);
|
||||
tf.setCaretColor(sel);
|
||||
tf.setSelectedTextColor(Color.WHITE); // Ensure selected text is readable on selection bg
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the active panel border uses the updated configuration color immediately
|
||||
SwingUtilities.invokeLater(() -> updateActivePanelBorder());
|
||||
}
|
||||
@ -750,6 +807,8 @@ public class MainWindow extends JFrame {
|
||||
if (container == null) return;
|
||||
container.setBackground(bg);
|
||||
boolean dark = isDark(bg);
|
||||
Color selColor = config != null ? config.getSelectionColor() : null;
|
||||
|
||||
for (Component c : container.getComponents()) {
|
||||
if (c instanceof JPanel || c instanceof JToolBar || c instanceof JScrollPane || c instanceof JViewport || c instanceof JTabbedPane || c instanceof JButton) {
|
||||
c.setBackground(bg);
|
||||
@ -757,6 +816,17 @@ public class MainWindow extends JFrame {
|
||||
if (c instanceof JLabel || c instanceof JCheckBox || c instanceof JRadioButton || c instanceof JButton) {
|
||||
c.setForeground(dark ? Color.WHITE : Color.BLACK);
|
||||
}
|
||||
if (c instanceof javax.swing.text.JTextComponent) {
|
||||
javax.swing.text.JTextComponent tc = (javax.swing.text.JTextComponent) c;
|
||||
tc.setBackground(bg);
|
||||
tc.setForeground(dark ? Color.WHITE : Color.BLACK);
|
||||
if (selColor != null) {
|
||||
tc.setSelectionColor(selColor);
|
||||
tc.setCaretColor(selColor);
|
||||
} else {
|
||||
tc.setCaretColor(dark ? Color.WHITE : Color.BLACK);
|
||||
}
|
||||
}
|
||||
if (c instanceof Container) {
|
||||
updateComponentBackground((Container) c, bg);
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ public class SearchDialog extends JDialog {
|
||||
private JComboBox<String> contentPatternCombo;
|
||||
private JCheckBox recursiveCheckBox;
|
||||
private JCheckBox contentSearchCheckBox;
|
||||
private JCheckBox archiveSearchCheckBox;
|
||||
private JTable resultsTable;
|
||||
private ResultsTableModel tableModel;
|
||||
private JButton searchButton;
|
||||
@ -112,13 +113,17 @@ public class SearchDialog extends JDialog {
|
||||
contentPatternCombo.setToolTipText("Text to search inside files");
|
||||
searchPanel.add(contentPatternCombo, gbc);
|
||||
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = 3;
|
||||
gbc.gridwidth = 2;
|
||||
contentSearchCheckBox = new JCheckBox("Search inside file contents", false);
|
||||
searchPanel.add(contentSearchCheckBox, gbc);
|
||||
|
||||
gbc.gridy = 4;
|
||||
archiveSearchCheckBox = new JCheckBox("Search inside archives", false);
|
||||
archiveSearchCheckBox.setMnemonic(KeyEvent.VK_R);
|
||||
searchPanel.add(archiveSearchCheckBox, gbc);
|
||||
|
||||
gbc.gridy = 5;
|
||||
JLabel pathLabel = new JLabel("Directory: " + searchDirectory.getAbsolutePath());
|
||||
pathLabel.setFont(pathLabel.getFont().deriveFont(Font.ITALIC));
|
||||
searchPanel.add(pathLabel, gbc);
|
||||
@ -296,6 +301,18 @@ public class SearchDialog extends JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
// Alt+R toggles archive search
|
||||
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_DOWN_MASK), "toggleArchiveSearch");
|
||||
getRootPane().getActionMap().put("toggleArchiveSearch", new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(java.awt.event.ActionEvent e) {
|
||||
if (archiveSearchCheckBox != null) {
|
||||
archiveSearchCheckBox.setSelected(!archiveSearchCheckBox.isSelected());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Escape closes the dialog (and cancels ongoing search)
|
||||
getRootPane().registerKeyboardAction(e -> {
|
||||
searching = false;
|
||||
@ -433,6 +450,7 @@ public class SearchDialog extends JDialog {
|
||||
}
|
||||
|
||||
final String pattern = isContentSearch ? contentPat : namePat;
|
||||
final boolean searchArchives = archiveSearchCheckBox != null && archiveSearchCheckBox.isSelected();
|
||||
|
||||
// Reset and show status
|
||||
foundCount = 0;
|
||||
@ -441,27 +459,29 @@ public class SearchDialog extends JDialog {
|
||||
statusProgressBar.setIndeterminate(true);
|
||||
|
||||
// Spustit vyhledávání v samostatném vlákně
|
||||
SwingWorker<Void, File> worker = new SwingWorker<Void, File>() {
|
||||
SwingWorker<Void, Object[]> worker = new SwingWorker<Void, Object[]>() {
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
if (isContentSearch) {
|
||||
FileOperations.searchContents(searchDirectory, pattern, recursiveCheckBox.isSelected(), file -> {
|
||||
FileOperations.searchContents(searchDirectory, pattern, recursiveCheckBox.isSelected(), searchArchives, (file, virtualPath) -> {
|
||||
if (!searching) return;
|
||||
publish(file);
|
||||
publish(new Object[]{file, virtualPath});
|
||||
});
|
||||
} else {
|
||||
FileOperations.search(searchDirectory, pattern, recursiveCheckBox.isSelected(), file -> {
|
||||
FileOperations.search(searchDirectory, pattern, recursiveCheckBox.isSelected(), searchArchives, (file, virtualPath) -> {
|
||||
if (!searching) return;
|
||||
publish(file);
|
||||
publish(new Object[]{file, virtualPath});
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process(List<File> chunks) {
|
||||
for (File file : chunks) {
|
||||
tableModel.addResult(new FileItem(file));
|
||||
protected void process(List<Object[]> chunks) {
|
||||
for (Object[] chunk : chunks) {
|
||||
File file = (File) chunk[0];
|
||||
String virtualPath = (String) chunk[1];
|
||||
tableModel.addResult(new FileItem(file, virtualPath));
|
||||
// update found count and status
|
||||
foundCount++;
|
||||
statusLabel.setText("Found " + foundCount + " — searching...");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user