未验证 提交 e02434d1 编写于 作者: S Skylot

fix(gui): confirm directory loading on file open (#1462)

上级 4586015f
......@@ -8,7 +8,6 @@ import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.dnd.DnDConstants;
......@@ -46,8 +45,6 @@ import javax.swing.Action;
import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
......@@ -67,7 +64,6 @@ import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
......@@ -88,6 +84,7 @@ import jadx.api.JavaNode;
import jadx.api.ResourceFile;
import jadx.api.plugins.utils.CommonFileUtils;
import jadx.core.Jadx;
import jadx.core.utils.ListUtils;
import jadx.core.utils.StringUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.files.FileUtils;
......@@ -118,6 +115,7 @@ import jadx.gui.ui.codearea.AbstractCodeContentPanel;
import jadx.gui.ui.codearea.EditorViewState;
import jadx.gui.ui.dialog.ADBDialog;
import jadx.gui.ui.dialog.AboutDialog;
import jadx.gui.ui.dialog.FileDialog;
import jadx.gui.ui.dialog.LogViewerDialog;
import jadx.gui.ui.dialog.RenameDialog;
import jadx.gui.ui.dialog.SearchDialog;
......@@ -144,7 +142,6 @@ import jadx.gui.utils.search.TextSearchIndex;
import static io.reactivex.internal.functions.Functions.EMPTY_RUNNABLE;
import static jadx.gui.utils.FileUtils.fileNamesToPaths;
import static jadx.gui.utils.FileUtils.toPaths;
import static javax.swing.KeyStroke.getKeyStroke;
public class MainWindow extends JFrame {
......@@ -284,63 +281,22 @@ public class MainWindow extends JFrame {
}
public void openFileOrProject() {
String title = NLS.str("file.open_title");
JFileChooser fileChooser = buildFileChooser(false, title);
int ret = fileChooser.showDialog(this, title);
if (ret == JFileChooser.APPROVE_OPTION) {
settings.setLastOpenFilePath(fileChooser.getCurrentDirectory().toPath());
open(toPaths(fileChooser.getSelectedFiles()));
FileDialog fileDialog = new FileDialog(this, FileDialog.OpenMode.OPEN);
List<Path> openPaths = fileDialog.show();
if (!openPaths.isEmpty()) {
settings.setLastOpenFilePath(fileDialog.getCurrentDir());
open(openPaths);
}
}
public void addFiles() {
String title = NLS.str("file.add_files_action");
JFileChooser fileChooser = buildFileChooser(true, title);
int ret = fileChooser.showDialog(this, title);
if (ret == JFileChooser.APPROVE_OPTION) {
List<Path> paths = new ArrayList<>(wrapper.getOpenPaths());
paths.addAll(toPaths(fileChooser.getSelectedFiles()));
open(paths);
FileDialog fileDialog = new FileDialog(this, FileDialog.OpenMode.ADD);
List<Path> addPaths = fileDialog.show();
if (!addPaths.isEmpty()) {
open(ListUtils.distinctMergeSortedLists(addPaths, wrapper.getOpenPaths()));
}
}
private JFileChooser buildFileChooser(boolean addFiles, String toolTipText) {
String[] exts;
if (addFiles) {
exts = new String[] { "apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc" };
} else {
exts = new String[] { JadxProject.PROJECT_EXTENSION, "apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc", "aab" };
}
String description = "Supported files: (" + Utils.arrayToStr(exts) + ')';
JFileChooser fileChooser = new JFileChooser() {
@Override
protected JDialog createDialog(Component parent) throws HeadlessException {
JDialog dialog = super.createDialog(parent);
dialog.setLocationRelativeTo(null);
settings.loadWindowPos(dialog);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
settings.saveWindowPos(dialog);
super.windowClosed(e);
}
});
return dialog;
}
};
fileChooser.setAcceptAllFileFilterUsed(true);
fileChooser.setFileFilter(new FileNameExtensionFilter(description, exts));
fileChooser.setMultiSelectionEnabled(true);
fileChooser.setToolTipText(toolTipText);
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
Path currentDirectory = settings.getLastOpenFilePath();
if (currentDirectory != null) {
fileChooser.setCurrentDirectory(currentDirectory.toFile());
}
return fileChooser;
}
private void newProject() {
if (!ensureProjectIsSaved()) {
return;
......@@ -359,45 +315,35 @@ public class MainWindow extends JFrame {
}
private void saveProjectAs() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setAcceptAllFileFilterUsed(true);
String[] exts = { JadxProject.PROJECT_EXTENSION };
String description = "supported files: " + Arrays.toString(exts).replace('[', '(').replace(']', ')');
fileChooser.setFileFilter(new FileNameExtensionFilter(description, exts));
fileChooser.setToolTipText(NLS.str("file.save_project"));
Path currentDirectory = settings.getLastSaveProjectPath();
if (currentDirectory != null) {
fileChooser.setCurrentDirectory(currentDirectory.toFile());
}
if (this.project.getFilePaths().size() == 1) {
FileDialog fileDialog = new FileDialog(this, FileDialog.OpenMode.SAVE_PROJECT);
if (project.getFilePaths().size() == 1) {
// If there is only one file loaded we suggest saving the jadx project file next to the loaded file
Path loadedFile = this.project.getFilePaths().get(0);
String fileName = loadedFile.getFileName() + "." + JadxProject.PROJECT_EXTENSION;
fileChooser.setSelectedFile(loadedFile.resolveSibling(fileName).toFile());
fileDialog.setSelectedFile(loadedFile.resolveSibling(fileName));
}
int ret = fileChooser.showSaveDialog(mainPanel);
if (ret == JFileChooser.APPROVE_OPTION) {
settings.setLastSaveProjectPath(fileChooser.getCurrentDirectory().toPath());
Path path = fileChooser.getSelectedFile().toPath();
if (!path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(JadxProject.PROJECT_EXTENSION)) {
path = path.resolveSibling(path.getFileName() + "." + JadxProject.PROJECT_EXTENSION);
}
if (Files.exists(path)) {
int res = JOptionPane.showConfirmDialog(
this,
NLS.str("confirm.save_as_message", path.getFileName()),
NLS.str("confirm.save_as_title"),
JOptionPane.YES_NO_OPTION);
if (res == JOptionPane.NO_OPTION) {
return;
}
List<Path> saveFiles = fileDialog.show();
if (saveFiles.isEmpty()) {
return;
}
settings.setLastSaveProjectPath(fileDialog.getCurrentDir());
Path savePath = saveFiles.get(0);
if (!savePath.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(JadxProject.PROJECT_EXTENSION)) {
savePath = savePath.resolveSibling(savePath.getFileName() + "." + JadxProject.PROJECT_EXTENSION);
}
if (Files.exists(savePath)) {
int res = JOptionPane.showConfirmDialog(
this,
NLS.str("confirm.save_as_message", savePath.getFileName()),
NLS.str("confirm.save_as_title"),
JOptionPane.YES_NO_OPTION);
if (res == JOptionPane.NO_OPTION) {
return;
}
project.saveAs(path);
settings.addRecentProject(path);
update();
}
project.saveAs(savePath);
settings.addRecentProject(savePath);
update();
}
void open(List<Path> paths) {
......@@ -646,29 +592,22 @@ public class MainWindow extends JFrame {
}
private void saveAll(boolean export) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setToolTipText(NLS.str("file.save_all_msg"));
Path currentDirectory = settings.getLastSaveFilePath();
if (currentDirectory != null) {
fileChooser.setCurrentDirectory(currentDirectory.toFile());
FileDialog fileDialog = new FileDialog(this, FileDialog.OpenMode.EXPORT);
List<Path> saveDirs = fileDialog.show();
if (saveDirs.isEmpty()) {
return;
}
int ret = fileChooser.showSaveDialog(mainPanel);
if (ret == JFileChooser.APPROVE_OPTION) {
JadxArgs decompilerArgs = wrapper.getArgs();
decompilerArgs.setExportAsGradleProject(export);
if (export) {
decompilerArgs.setSkipSources(false);
decompilerArgs.setSkipResources(false);
} else {
decompilerArgs.setSkipSources(settings.isSkipSources());
decompilerArgs.setSkipResources(settings.isSkipResources());
}
settings.setLastSaveFilePath(fileChooser.getCurrentDirectory().toPath());
backgroundExecutor.execute(new ExportTask(this, wrapper, fileChooser.getSelectedFile()));
JadxArgs decompilerArgs = wrapper.getArgs();
decompilerArgs.setExportAsGradleProject(export);
if (export) {
decompilerArgs.setSkipSources(false);
decompilerArgs.setSkipResources(false);
} else {
decompilerArgs.setSkipSources(settings.isSkipSources());
decompilerArgs.setSkipResources(settings.isSkipResources());
}
settings.setLastSaveFilePath(fileDialog.getCurrentDir());
backgroundExecutor.execute(new ExportTask(this, wrapper, saveDirs.get(0).toFile()));
}
public void initTree() {
......
package jadx.gui.ui.dialog;
import java.awt.Component;
import java.awt.HeadlessException;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jetbrains.annotations.Nullable;
import jadx.core.utils.Utils;
import jadx.gui.settings.JadxProject;
import jadx.gui.ui.MainWindow;
import jadx.gui.utils.FileUtils;
import jadx.gui.utils.NLS;
public class FileDialog {
public enum OpenMode {
OPEN, ADD, SAVE_PROJECT, EXPORT
}
private final MainWindow mainWindow;
private boolean isOpen;
private String title;
private List<String> fileExtList;
private int selectionMode = JFileChooser.FILES_AND_DIRECTORIES;
private @Nullable Path currentDir;
private @Nullable Path selectedFile;
public FileDialog(MainWindow mainWindow, OpenMode mode) {
this.mainWindow = mainWindow;
initForMode(mode);
}
public List<Path> show() {
FileChooser fileChooser = buildFileChooser();
int ret = isOpen ? fileChooser.showOpenDialog(mainWindow) : fileChooser.showSaveDialog(mainWindow);
if (ret != JFileChooser.APPROVE_OPTION) {
return Collections.emptyList();
}
currentDir = fileChooser.getCurrentDirectory().toPath();
return FileUtils.toPaths(fileChooser.getSelectedFiles());
}
public Path getCurrentDir() {
return currentDir;
}
public void setSelectedFile(Path path) {
this.selectedFile = path;
}
private void initForMode(OpenMode mode) {
switch (mode) {
case OPEN:
case ADD:
fileExtList = new ArrayList<>(Arrays.asList("apk", "dex", "jar", "class", "smali", "zip", "aar", "arsc"));
if (mode == OpenMode.OPEN) {
fileExtList.addAll(Arrays.asList(JadxProject.PROJECT_EXTENSION, "aab"));
title = NLS.str("file.open_title");
} else {
title = NLS.str("file.add_files_action");
}
selectionMode = JFileChooser.FILES_AND_DIRECTORIES;
currentDir = mainWindow.getSettings().getLastOpenFilePath();
isOpen = true;
break;
case SAVE_PROJECT:
title = NLS.str("file.save_project");
fileExtList = Collections.singletonList(JadxProject.PROJECT_EXTENSION);
selectionMode = JFileChooser.FILES_ONLY;
currentDir = mainWindow.getSettings().getLastSaveFilePath();
isOpen = false;
break;
case EXPORT:
title = NLS.str("file.save_all_msg");
fileExtList = Collections.emptyList();
selectionMode = JFileChooser.DIRECTORIES_ONLY;
currentDir = mainWindow.getSettings().getLastSaveFilePath();
isOpen = false;
break;
}
}
private FileChooser buildFileChooser() {
FileChooser fileChooser = new FileChooser();
fileChooser.setToolTipText(title);
fileChooser.setFileSelectionMode(selectionMode);
fileChooser.setMultiSelectionEnabled(isOpen);
fileChooser.setAcceptAllFileFilterUsed(true);
if (!fileExtList.isEmpty()) {
String description = NLS.str("file_dialog.supported_files") + ": (" + Utils.listToString(fileExtList) + ')';
fileChooser.setFileFilter(new FileNameExtensionFilter(description, fileExtList.toArray(new String[0])));
}
if (currentDir != null) {
fileChooser.setCurrentDirectory(currentDir.toFile());
}
if (selectedFile != null) {
fileChooser.setSelectedFile(selectedFile.toFile());
}
return fileChooser;
}
private class FileChooser extends JFileChooser {
@Override
protected JDialog createDialog(Component parent) throws HeadlessException {
JDialog dialog = super.createDialog(parent);
dialog.setTitle(title);
dialog.setLocationRelativeTo(null);
mainWindow.getSettings().loadWindowPos(dialog);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
mainWindow.getSettings().saveWindowPos(dialog);
super.windowClosed(e);
}
});
return dialog;
}
@Override
public void approveSelection() {
if (selectionMode == FILES_AND_DIRECTORIES) {
File currentFile = getSelectedFile();
if (currentFile.isDirectory()) {
int option = JOptionPane.showConfirmDialog(
mainWindow,
NLS.str("file_dialog.load_dir_confirm") + "\n " + currentFile,
NLS.str("file_dialog.load_dir_title"),
JOptionPane.YES_NO_OPTION);
if (option != JOptionPane.YES_OPTION) {
this.setCurrentDirectory(currentFile);
this.updateUI();
return;
}
}
}
super.approveSelection();
}
}
}
......@@ -80,6 +80,10 @@ common_dialog.add=Hinzufügen
common_dialog.update=Aktualisieren
common_dialog.remove=Entfernen
#file_dialog.supported_files=Supported files
#file_dialog.load_dir_title=Load directory
#file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=Öffnen
search_dialog.cancel=Beenden
search_dialog.open_by_name=Nach Text suchen:
......
......@@ -80,6 +80,10 @@ common_dialog.add=Add
common_dialog.update=Update
common_dialog.remove=Remove
file_dialog.supported_files=Supported files
file_dialog.load_dir_title=Load directory
file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=Open
search_dialog.cancel=Cancel
search_dialog.open_by_name=Search for text:
......
......@@ -80,6 +80,10 @@ nav.forward=Adelante
#common_dialog.update=Update
#common_dialog.remove=Remove
#file_dialog.supported_files=Supported files
#file_dialog.load_dir_title=Load directory
#file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=Abrir
search_dialog.cancel=Cancelar
search_dialog.open_by_name=Buscar texto:
......
......@@ -80,6 +80,10 @@ common_dialog.add=추가
common_dialog.update=업데이트
common_dialog.remove=삭제
#file_dialog.supported_files=Supported files
#file_dialog.load_dir_title=Load directory
#file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=열기
search_dialog.cancel=취소
search_dialog.open_by_name=텍스트 검색 :
......
......@@ -80,6 +80,10 @@ common_dialog.add=添加
common_dialog.update=更新
common_dialog.remove=移除
#file_dialog.supported_files=Supported files
#file_dialog.load_dir_title=Load directory
#file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=转到
search_dialog.cancel=取消
search_dialog.open_by_name=搜索文本:
......
......@@ -80,6 +80,10 @@ common_dialog.add=新增
common_dialog.update=更新
common_dialog.remove=移除
#file_dialog.supported_files=Supported files
#file_dialog.load_dir_title=Load directory
#file_dialog.load_dir_confirm=Load all files from directory?
search_dialog.open=開啟
search_dialog.cancel=取消
search_dialog.open_by_name=搜尋文字:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册