diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java index edd6bcb45e..7d804407d0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramManagerPlugin.java @@ -1018,6 +1018,11 @@ public class ProgramManagerPlugin extends Plugin implements ProgramManager { return; } + // Restore state should not ask about checking out since + // hopefully it is in the same state it was in when project + // was closed and state was saved. + openTask.setNoCheckout(); + try { new TaskLauncher(openTask, tool.getToolFrame(), 100); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/task/OpenProgramTask.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/task/OpenProgramTask.java index 7e232ab58e..055906427a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/task/OpenProgramTask.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/task/OpenProgramTask.java @@ -42,7 +42,8 @@ public class OpenProgramTask extends Task { private List programList = new ArrayList<>(); private TaskMonitor monitor; private final Object consumer; - private boolean silent; + private boolean silent; // if true operation does not permit interaction + private boolean noCheckout; // if true operation should not perform optional checkout private String openPromptText = "Open"; @@ -91,10 +92,25 @@ public class OpenProgramTask extends Task { domainFileInfoList.add(new DomainFileInfo(domainFile, version, forceReadOnly)); } + /** + * Invoking this method prior to task execution will prevent + * any confirmation interaction with the user (e.g., + * optional checkout, snapshot recovery, etc.). Errors + * may still be displayed if they occur. + */ public void setSilent() { this.silent = true; } + /** + * Invoking this method prior to task execution will prevent + * the use of optional checkout which require prompting the + * user. + */ + public void setNoCheckout() { + this.noCheckout = true; + } + public List getOpenPrograms() { return programList; } @@ -189,10 +205,7 @@ public class OpenProgramTask extends Task { private void openUnversionedFile(DomainFile domainFile) { String filename = domainFile.getName(); monitor.setMessage("Opening " + filename); - if (!silent && domainFile.canCheckout() && domainFile.isInWritableProject()) { - checkout(domainFile); - } - + performOptionalCheckout(domainFile); try { openFileMaybeUgrade(domainFile); } @@ -261,15 +274,20 @@ public class OpenProgramTask extends Task { return result.get(); } - private boolean checkout(DomainFile domainFile) { - User user = AppInfo.getActiveProject().getProjectData().getUser(); + private void performOptionalCheckout(DomainFile domainFile) { + + if (silent || noCheckout || !domainFile.canCheckout()) { + return; + } + + User user = domainFile.getParent().getProjectData().getUser(); CheckoutDialog dialog = new CheckoutDialog(domainFile, user); if (dialog.showDialog() == CheckoutDialog.CHECKOUT) { try { monitor.setMessage("Checking Out " + domainFile.getName()); if (domainFile.checkout(dialog.exclusiveCheckout(), monitor)) { - return true; + return; } Msg.showError(this, null, "Checkout Failed", "Exclusive checkout failed for: " + domainFile.getName() + "\nOne or more users have file checked out!"); @@ -284,7 +302,6 @@ public class OpenProgramTask extends Task { Msg.showError(this, null, "Error on Check Out", e.getMessage(), e); } } - return false; } static class DomainFileInfo { diff --git a/Ghidra/Framework/Docking/src/main/java/docking/widgets/HyperlinkComponent.java b/Ghidra/Framework/Docking/src/main/java/docking/widgets/HyperlinkComponent.java index 168dd1b7b3..1077beff74 100644 --- a/Ghidra/Framework/Docking/src/main/java/docking/widgets/HyperlinkComponent.java +++ b/Ghidra/Framework/Docking/src/main/java/docking/widgets/HyperlinkComponent.java @@ -114,6 +114,7 @@ public class HyperlinkComponent extends JPanel { // Also, if we call getPreferredSize(), then it will work. // textPane.getPreferredSize(); + getPreferredSize(); } public String getText() { diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java index aca4e79313..789316cc3b 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/main/datatable/ProjectDataTablePanel.java @@ -37,6 +37,7 @@ import ghidra.framework.main.FrontEndPlugin; import ghidra.framework.model.*; import ghidra.framework.plugintool.PluginTool; import ghidra.util.HelpLocation; +import ghidra.util.SystemUtilities; import ghidra.util.bean.GGlassPane; import ghidra.util.bean.GGlassPanePainter; @@ -268,10 +269,11 @@ public class ProjectDataTablePanel extends JPanel { capacityExceeded = true; this.projectData.removeDomainFolderChangeListener(changeListener); model.setProjectData(null); - - GGlassPane glassPane = (GGlassPane) gTable.getRootPane().getGlassPane(); - glassPane.removePainter(painter); - glassPane.addPainter(painter); + SystemUtilities.runSwingLater(() -> { + GGlassPane glassPane = (GGlassPane) gTable.getRootPane().getGlassPane(); + glassPane.removePainter(painter); + glassPane.addPainter(painter); + }); } }