* make sure permissions dialog is called on EDT
This commit is contained in:
parent
e185fdb990
commit
f22325b3dd
|
@ -28,6 +28,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.RunnableFuture;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -38,6 +41,7 @@ import javax.swing.JComponent;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
import net.filebot.ResourceManager;
|
import net.filebot.ResourceManager;
|
||||||
import net.filebot.Settings;
|
import net.filebot.Settings;
|
||||||
|
@ -106,71 +110,89 @@ public class DropToUnlock extends JList<File> {
|
||||||
}).filter(f -> f != null && isLockedFolder(f)).sorted().distinct().collect(Collectors.toList());
|
}).filter(f -> f != null && isLockedFolder(f)).sorted().distinct().collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean showUnlockFoldersDialog(Window owner, Collection<File> files) {
|
public static boolean showUnlockFoldersDialog(final Window owner, final Collection<File> files) {
|
||||||
final List<File> model = getParentFolders(files);
|
final List<File> model = getParentFolders(files);
|
||||||
|
|
||||||
// immediately return if there is nothing that needs to be unlocked
|
// immediately return if there is nothing that needs to be unlocked
|
||||||
if (model.isEmpty())
|
if (model.isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// try to restore permissions from previously stored security-scoped bookmarks as best as possible
|
// try to restore permissions from previously stored security-scoped bookmarks as best as possible
|
||||||
unlockBySecurityScopedBookmarks(model);
|
unlockBySecurityScopedBookmarks(model);
|
||||||
|
|
||||||
// check if we even need to unlock anything at this point
|
// check if we even need to unlock anything at this point
|
||||||
if (model.stream().allMatch(f -> !isLockedFolder(f)))
|
if (model.stream().allMatch(f -> !isLockedFolder(f))) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
final JDialog dialog = new JDialog(owner);
|
// show selection dialog on EDT
|
||||||
final AtomicBoolean dialogCancelled = new AtomicBoolean(true);
|
RunnableFuture<Boolean> showPermissionDialog = new FutureTask<Boolean>(new Callable<Boolean>() {
|
||||||
DropToUnlock d = new DropToUnlock(model) {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateLockStatus(File... folders) {
|
public Boolean call() throws Exception {
|
||||||
super.updateLockStatus(folders);
|
final JDialog dialog = new JDialog(owner);
|
||||||
|
final AtomicBoolean dialogCancelled = new AtomicBoolean(true);
|
||||||
|
DropToUnlock d = new DropToUnlock(model) {
|
||||||
|
|
||||||
// if all folders have been unlocked auto-close dialog
|
@Override
|
||||||
if (model.stream().allMatch(f -> !isLockedFolder(f))) {
|
public void updateLockStatus(File... folders) {
|
||||||
dialogCancelled.set(false);
|
super.updateLockStatus(folders);
|
||||||
invokeLater(750, () -> {
|
|
||||||
dialog.setVisible(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
d.setBorder(createEmptyBorder(5, 15, 120, 15));
|
|
||||||
|
|
||||||
JComponent c = (JComponent) dialog.getContentPane();
|
// if all folders have been unlocked auto-close dialog
|
||||||
c.setLayout(new MigLayout("insets 0, fill"));
|
if (model.stream().allMatch(f -> !isLockedFolder(f))) {
|
||||||
|
dialogCancelled.set(false);
|
||||||
|
invokeLater(750, () -> {
|
||||||
|
dialog.setVisible(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
d.setBorder(createEmptyBorder(5, 15, 120, 15));
|
||||||
|
|
||||||
HeaderPanel h = new HeaderPanel();
|
JComponent c = (JComponent) dialog.getContentPane();
|
||||||
h.getTitleLabel().setText("Folder Permissions Required");
|
c.setLayout(new MigLayout("insets 0, fill"));
|
||||||
h.getTitleLabel().setIcon(ResourceManager.getIcon("file.lock"));
|
|
||||||
h.getTitleLabel().setBorder(createEmptyBorder(0, 0, 0, 64));
|
|
||||||
c.add(h, "wmin 150px, hmin 75px, growx, dock north");
|
|
||||||
c.add(d, "wmin 150px, hmin 150px, grow");
|
|
||||||
|
|
||||||
dialog.setModal(true);
|
HeaderPanel h = new HeaderPanel();
|
||||||
dialog.setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE);
|
h.getTitleLabel().setText("Folder Permissions Required");
|
||||||
dialog.setSize(new Dimension(540, 420));
|
h.getTitleLabel().setIcon(ResourceManager.getIcon("file.lock"));
|
||||||
dialog.setResizable(false);
|
h.getTitleLabel().setBorder(createEmptyBorder(0, 0, 0, 64));
|
||||||
dialog.setLocationByPlatform(true);
|
c.add(h, "wmin 150px, hmin 75px, growx, dock north");
|
||||||
dialog.setAlwaysOnTop(true);
|
c.add(d, "wmin 150px, hmin 150px, grow");
|
||||||
|
|
||||||
// open required folders for easy drag and drop (a few milliseconds after the dialog has become visible)
|
dialog.setModal(true);
|
||||||
invokeLater(500, () -> {
|
dialog.setModalExclusionType(ModalExclusionType.TOOLKIT_EXCLUDE);
|
||||||
revealFiles(model);
|
dialog.setSize(new Dimension(540, 420));
|
||||||
|
dialog.setResizable(false);
|
||||||
|
dialog.setLocationByPlatform(true);
|
||||||
|
dialog.setAlwaysOnTop(true);
|
||||||
|
|
||||||
|
// open required folders for easy drag and drop (a few milliseconds after the dialog has become visible)
|
||||||
|
invokeLater(500, () -> {
|
||||||
|
revealFiles(model);
|
||||||
|
});
|
||||||
|
|
||||||
|
// show and wait for user input
|
||||||
|
dialog.setVisible(true);
|
||||||
|
|
||||||
|
// abort if user has closed the window before all folders have been unlocked
|
||||||
|
return !dialogCancelled.get();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// show and wait for user input
|
// show dialog on EDT and wait for user input
|
||||||
dialog.setVisible(true);
|
try {
|
||||||
|
SwingUtilities.invokeAndWait(showPermissionDialog);
|
||||||
|
|
||||||
// abort if user has closed the window before all folders have been unlocked
|
// store security-scoped bookmark if dialog was accepted
|
||||||
if (dialogCancelled.get())
|
if (showPermissionDialog.get()) {
|
||||||
return false;
|
storeSecurityScopedBookmarks(model);
|
||||||
|
return true;
|
||||||
// store security-scoped bookmarks
|
}
|
||||||
storeSecurityScopedBookmarks(model);
|
} catch (Exception e) {
|
||||||
return true;
|
Logger.getLogger(DropToUnlock.class.getName()).log(Level.WARNING, "NSURL.bookmarkDataWithOptions: " + e.toString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DropToUnlock(Collection<File> model) {
|
public DropToUnlock(Collection<File> model) {
|
||||||
|
|
Loading…
Reference in New Issue