/* * Copyright (c) 2006-2017 DMDirc Developers * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.dmdirc.addons.dcc.kde; import com.dmdirc.addons.dcc.DCCManager; import com.dmdirc.config.provider.AggregateConfigProvider; import java.awt.Component; import java.awt.HeadlessException; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JFileChooser; /** * JFileChooser that uses KDialog to show the actual chooser. This is quite hacky, and not * guarenteed to behave identically to JFileChooser, altho it tries to be as close as possible. * Almost a drop in replacement for JFileChooser, replace: new JFileChooser(); with: * KFileChooser.getFileChooser(); * * There are obviously some differences: - File filters must be set using setKDEFileFilter() not * using FileFilter objects. - FileSystemView's are ignored - showOpenDialog and showSaveDialog * shell kdialog, so only options available in kdialog work. - getFileChooser() will return a * JFileChooser object unless the DCC plugin's config option "general.useKFileChooser" is set to * "true" (defaults to false) and kdialog is in either /usr/bin or /bin - Selection mode * FILES_AND_DIRECTORIES can not be used */ public class KFileChooser extends JFileChooser { /** A version number for this class. */ private static final long serialVersionUID = 200806141; /** The plugin that this file chooser is for. */ private final DCCManager plugin; /** Used to read settings from. */ private final AggregateConfigProvider config; /** * Constructs a FileChooser pointing to the user's default directory. * * @param plugin The plugin that owns this KFileChooser */ private KFileChooser(final AggregateConfigProvider config, final DCCManager plugin) { this.plugin = plugin; this.config = config; } /** * Constructs a FileChooser using the given File as the path. * * @param plugin The plugin that owns this KFileChooser * @param currentDirectory Directory to use as the base directory */ private KFileChooser(final AggregateConfigProvider config, final DCCManager plugin, final File currentDirectory) { super(currentDirectory); this.plugin = plugin; this.config = config; } /** * Constructs a FileChooser using the given path. * * @param plugin The plugin that owns this KFileChooser * @param currentDirectoryPath Directory to use as the base directory */ private KFileChooser(final AggregateConfigProvider config, final DCCManager plugin, final String currentDirectoryPath) { super(currentDirectoryPath); this.plugin = plugin; this.config = config; } /** * Should a KFileChooser be used rather than a JFileChooser? * * @param config Config manager * @param plugin The DCC Plugin that is requesting a chooser * * @return return true if getFileChooser() will return a KFileChooser not a JFileChooser */ public static boolean useKFileChooser(final AggregateConfigProvider config, final DCCManager plugin) { return KDialogProcess.hasKDialog() && config.getOptionBool(plugin.getDomain(), "general.useKFileChooser"); } /** * Constructs a FileChooser pointing to the user's default directory. * * @param config Config provider used to retrieve settings * @param plugin The DCC Plugin that is requesting a chooser * * @return The relevant FileChooser */ public static JFileChooser getFileChooser(final AggregateConfigProvider config, final DCCManager plugin) { return useKFileChooser(config, plugin) ? new KFileChooser(config, plugin) : new JFileChooser(); } /** * Constructs a FileChooser using the given File as the path. * * @param config Config provider used to retrieve settings * @param plugin The DCC Plugin that is requesting a chooser * @param currentDirectory Directory to use as the base directory * * @return The relevant FileChooser */ public static JFileChooser getFileChooser(final AggregateConfigProvider config, final DCCManager plugin, final File currentDirectory) { return useKFileChooser(config, plugin) ? new KFileChooser(config, plugin, currentDirectory) : new JFileChooser(currentDirectory); } /** * Constructs a FileChooser using the given path. * * @param config Config provider used to retrieve settings * @param plugin The DCC Plugin that is requesting a chooser * @param currentDirectoryPath Directory to use as the base directory * * @return The relevant FileChooser */ public static JFileChooser getFileChooser(final AggregateConfigProvider config, final DCCManager plugin, final String currentDirectoryPath) { return useKFileChooser(config, plugin) ? new KFileChooser(config, plugin, currentDirectoryPath) : new JFileChooser(currentDirectoryPath); } @Override public int showOpenDialog(final Component parent) throws HeadlessException { if (!useKFileChooser(config, plugin)) { return super.showOpenDialog(parent); } final ArrayList params = new ArrayList<>(); if (isMultiSelectionEnabled()) { params.add("--multiple"); params.add("--separate-output"); } if (getDialogTitle() != null && !getDialogTitle().isEmpty()) { params.add("--caption"); params.add(getDialogTitle()); } if (getFileSelectionMode() == DIRECTORIES_ONLY) { params.add("--getexistingdirectory"); } else { params.add("--getopenfilename"); } if (getSelectedFile() != null && getFileSelectionMode() != DIRECTORIES_ONLY && !getSelectedFile().getPath().isEmpty()) { if (getSelectedFile().getPath().charAt(0) != '/') { params.add(getCurrentDirectory().getPath() + File.separator + getSelectedFile(). getPath()); } else { params.add(getSelectedFile().getPath()); } } else if (getCurrentDirectory() != null) { params.add(getCurrentDirectory().getPath()); } final KDialogProcess kdp; try { kdp = new KDialogProcess(params.toArray(new String[params.size()])); kdp.waitFor(); } catch (IOException | InterruptedException e) { return JFileChooser.ERROR_OPTION; } if (kdp.getProcess().exitValue() == 0) { if (isMultiSelectionEnabled()) { final List list = kdp.getStdOut(); final File[] fileList = new File[list.size()]; for (int i = 0; i < list.size(); ++i) { fileList[i] = new File(list.get(i)); } setSelectedFiles(fileList); } else { setSelectedFile(new File(kdp.getStdOut().get(0))); } return JFileChooser.APPROVE_OPTION; } else { return JFileChooser.ERROR_OPTION; } } @Override public int showSaveDialog(final Component parent) throws HeadlessException { if (!useKFileChooser(config, plugin)) { return super.showSaveDialog(parent); } final ArrayList params = new ArrayList<>(); if (getDialogTitle() != null && !getDialogTitle().isEmpty()) { params.add("--caption"); params.add(getDialogTitle()); } params.add("--getsavefilename"); if (getSelectedFile() != null && !getSelectedFile().getPath().isEmpty()) { if (getSelectedFile().getPath().charAt(0) != '/') { params.add(getCurrentDirectory().getPath() + File.separator + getSelectedFile(). getPath()); } else { params.add(getSelectedFile().getPath()); } } else if (getCurrentDirectory() != null) { params.add(getCurrentDirectory().getPath()); } final KDialogProcess kdp; try { kdp = new KDialogProcess(params.toArray(new String[params.size()])); kdp.waitFor(); } catch (IOException | InterruptedException e) { return JFileChooser.ERROR_OPTION; } if (kdp.getProcess().exitValue() == 0) { setSelectedFile(new File(kdp.getStdOut().get(0))); return JFileChooser.APPROVE_OPTION; } else { return JFileChooser.ERROR_OPTION; } } }