mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-10 10:28:10 +08:00
Merge remote-tracking branch 'origin/GP-6756-dragonmacher-save-as-folder-issue' into Ghidra_12.1
This commit is contained in:
+6
-2
@@ -214,10 +214,14 @@ class ProgramSaveManager {
|
||||
}
|
||||
try {
|
||||
DataTreeDialog dialog = getSaveDialog();
|
||||
String filename = program.getDomainFile().getName();
|
||||
DomainFile domainFile = program.getDomainFile();
|
||||
String filename = domainFile.getName();
|
||||
dialog.setTitle("Save As (" + filename + ")");
|
||||
dialog.setNameText(filename + ".1");
|
||||
dialog.setSelectedFolder(program.getDomainFile().getParent());
|
||||
|
||||
DomainFolder parent = domainFile.getParent();
|
||||
dialog.setSelectedFolder(parent);
|
||||
|
||||
treeDialogCancelled = true;
|
||||
tool.showDialog(dialog);
|
||||
if (!treeDialogCancelled) {
|
||||
|
||||
+109
-70
@@ -193,6 +193,10 @@ public abstract class AbstractDataTreeDialog extends DialogComponentProvider
|
||||
return nameField.getText();
|
||||
}
|
||||
|
||||
public String getFolderText() {
|
||||
return folderNameLabel.getText();
|
||||
}
|
||||
|
||||
public void setNameText(String name) {
|
||||
// We need to run this code in a task since the tree may already be processing other tasks
|
||||
// that would override this setting when they are run. But putting this task in the queue,
|
||||
@@ -246,89 +250,124 @@ public abstract class AbstractDataTreeDialog extends DialogComponentProvider
|
||||
return domainFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* TreeSelectionListener method that is called whenever the value of the selection changes.
|
||||
* @param e the event that characterizes the change.
|
||||
*/
|
||||
@Override
|
||||
public void valueChanged(GTreeSelectionEvent e) {
|
||||
clearStatusText();
|
||||
|
||||
if (type == CHOOSE_FOLDER) {
|
||||
domainFolder = treePanel.getSelectedDomainFolder();
|
||||
if (domainFolder != null) {
|
||||
DomainFolder folderParent = domainFolder.getParent();
|
||||
if (folderParent != null) {
|
||||
folderNameLabel.setText(folderParent.getPathname());
|
||||
}
|
||||
else {
|
||||
folderNameLabel.setText(" ");
|
||||
}
|
||||
|
||||
nameField.setText(domainFolder.getName());
|
||||
}
|
||||
else {
|
||||
domainFile = treePanel.getSelectedDomainFile();
|
||||
if (domainFile != null) {
|
||||
domainFolder = domainFile.getParent();
|
||||
DomainFolder grandParent = domainFolder.getParent();
|
||||
if (grandParent != null) {
|
||||
folderNameLabel.setText(grandParent.getPathname());
|
||||
}
|
||||
else {
|
||||
folderNameLabel.setText("");
|
||||
}
|
||||
|
||||
nameField.setText(domainFolder.getName());
|
||||
}
|
||||
else {
|
||||
domainFolder = project.getProjectData().getRootFolder();
|
||||
folderNameLabel.setText(domainFolder.getPathname());
|
||||
nameField.setText(domainFolder.getName());
|
||||
}
|
||||
}
|
||||
updateFromTreeSelectionInFolderMode();
|
||||
}
|
||||
else {
|
||||
domainFile = treePanel.getSelectedDomainFile();
|
||||
if (domainFile != null) {
|
||||
LinkFileInfo linkInfo = domainFile.getLinkInfo();
|
||||
if (linkInfo != null && linkInfo.isFolderLink()) {
|
||||
// Ensure we don't have a folder name conflict
|
||||
if (domainFile.getParent().getFolder(domainFile.getName()) == null) {
|
||||
domainFolder = linkInfo.getLinkedFolder();
|
||||
domainFile = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
folderNameLabel.setText(domainFile.getParent().getPathname());
|
||||
nameField.setText(domainFile.getName());
|
||||
domainFolder = domainFile.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (domainFile == null) {
|
||||
if (domainFolder == null) {
|
||||
domainFolder = treePanel.getSelectedDomainFolder();
|
||||
if (domainFolder == null) {
|
||||
domainFolder = project.getProjectData().getRootFolder();
|
||||
}
|
||||
}
|
||||
folderNameLabel.setText(domainFolder.getPathname());
|
||||
if (nameField.isEditable()) {
|
||||
if (nameField.getText().length() > 0) {
|
||||
nameField.selectAll();
|
||||
}
|
||||
}
|
||||
else {
|
||||
nameField.setText("");
|
||||
}
|
||||
}
|
||||
updateFromTreeSelectionInFileMode();
|
||||
}
|
||||
|
||||
String text = nameField.getText();
|
||||
setOkEnabled((text != null) && !text.isEmpty());
|
||||
}
|
||||
|
||||
private void updateFromTreeSelectionInFileMode() {
|
||||
DomainFile newFile = treePanel.getSelectedDomainFile();
|
||||
if (isFolderLink(newFile)) {
|
||||
updateFromFolderLink(newFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// not a folder link; see if we have a new file selected
|
||||
if (newFile != null) {
|
||||
domainFile = newFile;
|
||||
domainFolder = domainFile.getParent();
|
||||
String pathname = domainFolder.getPathname();
|
||||
folderNameLabel.setText(pathname);
|
||||
String filename = domainFile.getName();
|
||||
nameField.setText(filename);
|
||||
return;
|
||||
}
|
||||
|
||||
// No selected domain file
|
||||
domainFile = null;
|
||||
domainFolder = getSelectedFolder();
|
||||
String pathname = domainFolder.getPathname();
|
||||
folderNameLabel.setText(pathname);
|
||||
updateNameFieldTextForNoFileSelected();
|
||||
}
|
||||
|
||||
private void updateNameFieldTextForNoFileSelected() {
|
||||
if (!nameField.isEditable()) {
|
||||
nameField.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nameField.getText().length() > 0) {
|
||||
nameField.selectAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFromFolderLink(DomainFile newFile) {
|
||||
|
||||
LinkFileInfo linkInfo = newFile.getLinkInfo();
|
||||
DomainFolder folder = newFile.getParent();
|
||||
String filename = newFile.getName();
|
||||
|
||||
// Ensure we don't have a folder name conflict
|
||||
if (folder.getFolder(filename) == null) {
|
||||
domainFolder = linkInfo.getLinkedFolder();
|
||||
if (domainFolder == null) {
|
||||
domainFolder = getSelectedFolder();
|
||||
}
|
||||
|
||||
domainFile = null;
|
||||
folderNameLabel.setText(domainFolder.getPathname());
|
||||
updateNameFieldTextForNoFileSelected();
|
||||
return;
|
||||
}
|
||||
|
||||
domainFile = newFile;
|
||||
folderNameLabel.setText(folder.getPathname());
|
||||
nameField.setText(filename);
|
||||
domainFolder = folder;
|
||||
}
|
||||
|
||||
private boolean isFolderLink(DomainFile file) {
|
||||
if (file == null) {
|
||||
return false;
|
||||
}
|
||||
LinkFileInfo linkInfo = file.getLinkInfo();
|
||||
return linkInfo != null && linkInfo.isFolderLink();
|
||||
}
|
||||
|
||||
private void updateFromTreeSelectionInFolderMode() {
|
||||
|
||||
// The tree selection has changed and we are in FOLDER mode. Update the folder selection
|
||||
// based on type of node selected.
|
||||
domainFolder = getSelectedFolder();
|
||||
DomainFolder folderParent = domainFolder.getParent();
|
||||
if (folderParent == null) {
|
||||
folderParent = domainFolder; // root folder; no parent
|
||||
}
|
||||
|
||||
folderNameLabel.setText(folderParent.getPathname());
|
||||
nameField.setText(domainFolder.getName());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the selected folder, or the selected file's parent or the root folder.
|
||||
* @return the folder
|
||||
*/
|
||||
private DomainFolder getSelectedFolder() {
|
||||
DomainFolder folder = treePanel.getSelectedDomainFolder();
|
||||
if (folder != null) {
|
||||
return folder;
|
||||
}
|
||||
|
||||
DomainFile file = treePanel.getSelectedDomainFile();
|
||||
if (file != null) {
|
||||
return file.getParent();
|
||||
}
|
||||
|
||||
return project.getProjectData().getRootFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
int index = projectComboBox.getSelectedIndex();
|
||||
|
||||
+52
-6
@@ -41,6 +41,8 @@ import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
|
||||
private static final String TEST_FOLDER_NAME = "TestFolder";
|
||||
|
||||
private TestEnv env;
|
||||
private FrontEndTool frontEndTool;
|
||||
private DataTreeDialog dialog;
|
||||
@@ -70,6 +72,10 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
DomainFolder domainFolder = ProjectDataUtils.createDomainFolderPath(rootFolder, path);
|
||||
result.add(domainFolder.createFile(filename, p, TaskMonitor.DUMMY));
|
||||
}
|
||||
|
||||
// add a test folder
|
||||
ProjectDataUtils.createDomainFolderPath(rootFolder, "/" + TEST_FOLDER_NAME);
|
||||
|
||||
builder.dispose();
|
||||
waitForSwing();
|
||||
return result;
|
||||
@@ -116,7 +122,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertNameHasText(true);
|
||||
|
||||
// select a folder--text remains; button enabled
|
||||
selectFolder();
|
||||
selectRootFolder();
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
|
||||
@@ -125,6 +131,16 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
|
||||
// select a non-root folder--text remains; button enabled
|
||||
selectTestFolder();
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
assertFolderText("/" + TEST_FOLDER_NAME);
|
||||
|
||||
deselectFolder();
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
|
||||
// clear text--disabled
|
||||
clearText();
|
||||
assertOK(false);
|
||||
@@ -147,7 +163,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertNameHasText(true);
|
||||
|
||||
// select a folder--text remains; button enabled
|
||||
selectFolder();
|
||||
selectRootFolder();
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
|
||||
@@ -185,7 +201,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertNameHasText(true); // "/"
|
||||
|
||||
// select a folder--enabled
|
||||
selectFolder();
|
||||
selectRootFolder();
|
||||
assertOK(true);
|
||||
assertNameHasText(true);
|
||||
|
||||
@@ -212,7 +228,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertNameHasText(false);
|
||||
|
||||
// select a folder--disabled
|
||||
selectFolder();
|
||||
selectRootFolder();
|
||||
assertOK(false);
|
||||
|
||||
// de-select a folder--disabled
|
||||
@@ -237,7 +253,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
assertNameHasText(false);
|
||||
|
||||
// select a folder--disabled
|
||||
selectFolder();
|
||||
selectRootFolder();
|
||||
assertOK(false);
|
||||
|
||||
// de-select a folder--disabled
|
||||
@@ -321,7 +337,7 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
});
|
||||
}
|
||||
|
||||
private void selectFolder() {
|
||||
private void selectRootFolder() {
|
||||
final AtomicBoolean result = new AtomicBoolean(false);
|
||||
final GTree gTree = getGTree();
|
||||
runSwing(() -> {
|
||||
@@ -340,6 +356,31 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
waitForTree(gTree);
|
||||
}
|
||||
|
||||
private void selectTestFolder() {
|
||||
|
||||
AtomicBoolean result = new AtomicBoolean(false);
|
||||
GTree gTree = getGTree();
|
||||
runSwing(() -> {
|
||||
GTreeNode root = gTree.getViewRoot();
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GTreeNode folderNode = root.getChild(TEST_FOLDER_NAME);
|
||||
if (folderNode != null) {
|
||||
gTree.expandPath(root);
|
||||
gTree.setSelectedNode(folderNode);
|
||||
result.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
if (!result.get()) {
|
||||
Assert.fail("Unable to select root folder");
|
||||
}
|
||||
|
||||
waitForTree(gTree);
|
||||
}
|
||||
|
||||
private void deselectFile() {
|
||||
clearSelection();
|
||||
}
|
||||
@@ -350,6 +391,11 @@ public class DataTreeDialogTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
waitForTree(gTree);
|
||||
}
|
||||
|
||||
private void assertFolderText(String expectedName) {
|
||||
String actualName = runSwing(() -> dialog.getFolderText());
|
||||
assertEquals("Dialog folder path not correct", expectedName, actualName);
|
||||
}
|
||||
|
||||
private void assertNameHasText(boolean hasText) {
|
||||
final AtomicBoolean result = new AtomicBoolean();
|
||||
runSwing(() -> {
|
||||
|
||||
Reference in New Issue
Block a user