package org.jabref.gui.push; import java.io.IOException; import java.util.List; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTextField; import org.jabref.Globals; import org.jabref.gui.BasePanel; import org.jabref.gui.DialogService; import org.jabref.gui.FXDialogService; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.FileDialogConfiguration; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.OS; import org.jabref.model.database.BibDatabase; import org.jabref.model.entry.BibEntry; import org.jabref.model.metadata.MetaData; import org.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Abstract class for pushing entries into different editors. */ public abstract class AbstractPushToApplication implements PushToApplication { private static final Log LOGGER = LogFactory.getLog(AbstractPushToApplication.class); protected boolean couldNotCall; // Set to true in case the command could not be executed, e.g., if the file is not found protected boolean couldNotConnect; // Set to true in case the tunnel to the program (if one is used) does not operate protected boolean notDefined; // Set to true if the corresponding path is not defined in the preferences protected JPanel settings; protected final JTextField path = new JTextField(30); protected String commandPath; protected String commandPathPreferenceKey; protected FormBuilder builder; @Override public String getName() { return Localization.menuTitle("Push entries to external application (%0)", getApplicationName()); } @Override public String getTooltip() { return Localization.lang("Push to %0", getApplicationName()); } @Override public void pushEntries(BibDatabase database, List<BibEntry> entries, String keyString, MetaData metaData) { couldNotConnect = false; couldNotCall = false; notDefined = false; initParameters(); commandPath = Globals.prefs.get(commandPathPreferenceKey); // Check if a path to the command has been specified if ((commandPath == null) || commandPath.trim().isEmpty()) { notDefined = true; return; } // Execute command try { if (OS.OS_X) { String[] commands = getCommandLine(keyString); Runtime.getRuntime().exec("open -a " + commands[0] + " -n --args " + commands[1] + " " + commands[2]); } else { Runtime.getRuntime().exec(getCommandLine(keyString)); } } // In case it did not work catch (IOException excep) { couldNotCall = true; LOGGER.warn("Error: Could not call executable '" + commandPath + "'.", excep); } } @Override public void operationCompleted(BasePanel panel) { if (notDefined) { panel.output(Localization.lang("Error") + ": " + Localization.lang("Path to %0 not defined", getApplicationName()) + "."); } else if (couldNotCall) { panel.output(Localization.lang("Error") + ": " + Localization.lang("Could not call executable") + " '" + commandPath + "'."); } else if (couldNotConnect) { panel.output(Localization.lang("Error") + ": " + Localization.lang("Could not connect to %0", getApplicationName()) + "."); } else { panel.output(Localization.lang("Pushed citations to %0", getApplicationName()) + "."); } } @Override public boolean requiresBibtexKeys() { return true; } /** * Function to get the command to be executed for pushing keys to be cited * * @param keyString String containing the Bibtex keys to be pushed to the application * @return String array with the command to call and its arguments */ @SuppressWarnings("unused") protected String[] getCommandLine(String keyString) { return new String[0]; } /** * Function to get the command name in case it is different from the application name * * @return String with the command name */ protected String getCommandName() { return null; } @Override public JPanel getSettingsPanel() { initParameters(); commandPath = Globals.prefs.get(commandPathPreferenceKey); if (settings == null) { initSettingsPanel(); } path.setText(commandPath); return settings; } /** * Function to initialize parameters. Currently it is expected that commandPathPreferenceKey is set to the path of * the application. */ protected abstract void initParameters(); /** * Create a FormBuilder, fill it with a textbox for the path and store the JPanel in settings */ protected void initSettingsPanel() { builder = FormBuilder.create(); builder.layout(new FormLayout("left:pref, 4dlu, fill:pref:grow, 4dlu, fill:pref", "p")); StringBuilder label = new StringBuilder(Localization.lang("Path to %0", getApplicationName())); // In case the application name and the actual command is not the same, add the command in brackets if (getCommandName() == null) { label.append(':'); } else { label.append(" (").append(getCommandName()).append("):"); } builder.add(label.toString()).xy(1, 1); builder.add(path).xy(3, 1); JButton browse = new JButton(Localization.lang("Browse")); FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder() .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)).build(); DialogService ds = new FXDialogService(); browse.addActionListener( e -> DefaultTaskExecutor.runInJavaFXThread(() -> ds.showFileOpenDialog(fileDialogConfiguration)) .ifPresent(f -> path.setText(f.toAbsolutePath().toString()))); builder.add(browse).xy(5, 1); settings = builder.build(); } @Override public void storeSettings() { Globals.prefs.put(commandPathPreferenceKey, path.getText()); } protected String getCiteCommand() { return Globals.prefs.get(JabRefPreferences.CITE_COMMAND); } }