package org.jabref.gui.openoffice;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
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.IconTheme;
import org.jabref.gui.JabRefFrame;
import org.jabref.gui.SidePaneComponent;
import org.jabref.gui.SidePaneManager;
import org.jabref.gui.desktop.JabRefDesktop;
import org.jabref.gui.desktop.os.NativeDesktop;
import org.jabref.gui.help.HelpAction;
import org.jabref.gui.keyboard.KeyBinding;
import org.jabref.gui.undo.NamedCompound;
import org.jabref.gui.undo.UndoableKeyChange;
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.gui.util.DirectoryDialogConfiguration;
import org.jabref.gui.util.FileDialogConfiguration;
import org.jabref.gui.worker.AbstractWorker;
import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternPreferences;
import org.jabref.logic.bibtexkeypattern.BibtexKeyPatternUtil;
import org.jabref.logic.help.HelpFile;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.openoffice.OOBibStyle;
import org.jabref.logic.openoffice.OpenOfficePreferences;
import org.jabref.logic.openoffice.StyleLoader;
import org.jabref.logic.openoffice.UndefinedParagraphFormatException;
import org.jabref.logic.util.OS;
import org.jabref.logic.util.io.FileUtil;
import org.jabref.model.Defaults;
import org.jabref.model.database.BibDatabase;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.FormBuilder;
import com.jgoodies.forms.layout.FormLayout;
import com.sun.star.beans.IllegalTypeException;
import com.sun.star.beans.NotRemoveableException;
import com.sun.star.beans.PropertyExistException;
import com.sun.star.beans.PropertyVetoException;
import com.sun.star.beans.UnknownPropertyException;
import com.sun.star.comp.helper.BootstrapException;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.lang.WrappedTargetException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This test panel can be opened by reflection from JabRef, passing the JabRefFrame as an
* argument to the start() method. It displays buttons for testing interaction functions
* between JabRef and OpenOffice.
*/
public class OpenOfficePanel extends AbstractWorker {
private static final Log LOGGER = LogFactory.getLog(OpenOfficePanel.class);
private OpenOfficeSidePanel sidePane;
private JDialog diag;
private final JButton connect;
private final JButton manualConnect;
private final JButton selectDocument;
private final JButton setStyleFile = new JButton(Localization.lang("Select style"));
private final JButton pushEntries = new JButton(Localization.lang("Cite"));
private final JButton pushEntriesInt = new JButton(Localization.lang("Cite in-text"));
private final JButton pushEntriesEmpty = new JButton(Localization.lang("Insert empty citation"));
private final JButton pushEntriesAdvanced = new JButton(Localization.lang("Cite special"));
private final JButton update;
private final JButton merge = new JButton(Localization.lang("Merge citations"));
private final JButton manageCitations = new JButton(Localization.lang("Manage citations"));
private final JButton exportCitations = new JButton(Localization.lang("Export cited"));
private final JButton settingsB = new JButton(Localization.lang("Settings"));
private final JButton help = new HelpAction(Localization.lang("OpenOffice/LibreOffice integration"),
HelpFile.OPENOFFICE_LIBREOFFICE).getHelpButton();
private OOBibBase ooBase;
private JabRefFrame frame;
private OOBibStyle style;
private StyleSelectDialog styleDialog;
private boolean dialogOkPressed;
private IOException connectException;
private final OpenOfficePreferences preferences;
private final StyleLoader loader;
public OpenOfficePanel(JabRefFrame jabRefFrame, SidePaneManager spManager) {
Icon connectImage = IconTheme.JabRefIcon.CONNECT_OPEN_OFFICE.getSmallIcon();
connect = new JButton(connectImage);
manualConnect = new JButton(connectImage);
connect.setToolTipText(Localization.lang("Connect"));
manualConnect.setToolTipText(Localization.lang("Manual connect"));
connect.setPreferredSize(new Dimension(24, 24));
manualConnect.setPreferredSize(new Dimension(24, 24));
selectDocument = new JButton(IconTheme.JabRefIcon.OPEN.getSmallIcon());
selectDocument.setToolTipText(Localization.lang("Select Writer document"));
selectDocument.setPreferredSize(new Dimension(24, 24));
update = new JButton(IconTheme.JabRefIcon.REFRESH.getSmallIcon());
update.setToolTipText(Localization.lang("Sync OpenOffice/LibreOffice bibliography"));
update.setPreferredSize(new Dimension(24, 24));
preferences = new OpenOfficePreferences(Globals.prefs);
loader = new StyleLoader(preferences,
Globals.prefs.getLayoutFormatterPreferences(Globals.journalAbbreviationLoader),
Globals.prefs.getDefaultEncoding());
this.frame = jabRefFrame;
sidePane = new OpenOfficeSidePanel(spManager, IconTheme.getImage("openoffice"), "OpenOffice/LibreOffice", preferences);
initPanel();
spManager.register(sidePane);
}
private void initPanel() {
connect.addActionListener(e -> connect(true));
manualConnect.addActionListener(e -> connect(false));
selectDocument.setToolTipText(Localization.lang("Select which open Writer document to work on"));
selectDocument.addActionListener(e -> {
try {
ooBase.selectDocument();
frame.output(Localization.lang("Connected to document") + ": "
+ ooBase.getCurrentDocumentTitle().orElse(""));
} catch (UnknownPropertyException | WrappedTargetException | IndexOutOfBoundsException |
NoSuchElementException | NoDocumentException ex) {
JOptionPane.showMessageDialog(frame, ex.getMessage(), Localization.lang("Error"),
JOptionPane.ERROR_MESSAGE);
LOGGER.warn("Problem connecting", ex);
}
});
setStyleFile.addActionListener(event -> {
if (styleDialog == null) {
styleDialog = new StyleSelectDialog(frame, preferences, loader);
}
styleDialog.setVisible(true);
styleDialog.getStyle().ifPresent(selectedStyle -> {
style = selectedStyle;
try {
style.ensureUpToDate();
} catch (IOException e) {
LOGGER.warn("Unable to reload style file '" + style.getPath() + "'", e);
}
frame.setStatus(Localization.lang("Current style is '%0'", style.getName()));
});
});
pushEntries.setToolTipText(Localization.lang("Cite selected entries between parenthesis"));
pushEntries.addActionListener(e -> pushEntries(true, true, false));
pushEntriesInt.setToolTipText(Localization.lang("Cite selected entries with in-text citation"));
pushEntriesInt.addActionListener(e -> pushEntries(false, true, false));
pushEntriesEmpty.setToolTipText(
Localization.lang("Insert a citation without text (the entry will appear in the reference list)"));
pushEntriesEmpty.addActionListener(e -> pushEntries(false, false, false));
pushEntriesAdvanced.setToolTipText(Localization.lang("Cite selected entries with extra information"));
pushEntriesAdvanced.addActionListener(e -> pushEntries(false, true, true));
update.setToolTipText(Localization.lang("Ensure that the bibliography is up-to-date"));
Action updateAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
try {
if (style == null) {
style = loader.getUsedStyle();
} else {
style.ensureUpToDate();
}
ooBase.updateSortedReferenceMarks();
List<BibDatabase> databases = getBaseList();
List<String> unresolvedKeys = ooBase.refreshCiteMarkers(databases, style);
ooBase.rebuildBibTextSection(databases, style);
if (!unresolvedKeys.isEmpty()) {
JOptionPane.showMessageDialog(frame,
Localization.lang(
"Your OpenOffice/LibreOffice document references the BibTeX key '%0', which could not be found in your current library.",
unresolvedKeys.get(0)),
Localization.lang("Unable to synchronize bibliography"), JOptionPane.ERROR_MESSAGE);
}
} catch (UndefinedCharacterFormatException ex) {
reportUndefinedCharacterFormat(ex);
} catch (UndefinedParagraphFormatException ex) {
reportUndefinedParagraphFormat(ex);
} catch (ConnectionLostException ex) {
showConnectionLostErrorMessage();
} catch (IOException ex) {
JOptionPane.showMessageDialog(frame,
Localization
.lang("You must select either a valid style file, or use one of the default styles."),
Localization.lang("No valid style file defined"), JOptionPane.ERROR_MESSAGE);
LOGGER.warn("Problem with style file", ex);
} catch (BibEntryNotFoundException ex) {
JOptionPane.showMessageDialog(frame,
Localization.lang(
"Your OpenOffice/LibreOffice document references the BibTeX key '%0', which could not be found in your current library.",
ex.getBibtexKey()),
Localization.lang("Unable to synchronize bibliography"), JOptionPane.ERROR_MESSAGE);
LOGGER.debug("BibEntry not found", ex);
} catch (com.sun.star.lang.IllegalArgumentException | PropertyVetoException | UnknownPropertyException | WrappedTargetException | NoSuchElementException |
CreationException ex) {
LOGGER.warn("Could not update bibliography", ex);
}
}
};
update.addActionListener(updateAction);
merge.setToolTipText(Localization.lang("Combine pairs of citations that are separated by spaces only"));
merge.addActionListener(e -> {
try {
ooBase.combineCiteMarkers(getBaseList(), style);
} catch (UndefinedCharacterFormatException ex) {
reportUndefinedCharacterFormat(ex);
} catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException |
CreationException | NoSuchElementException | WrappedTargetException | IOException |
BibEntryNotFoundException ex) {
LOGGER.warn("Problem combining cite markers", ex);
}
});
settingsB.addActionListener(e -> showSettingsPopup());
manageCitations.addActionListener(e -> {
try {
CitationManager cm = new CitationManager(frame, ooBase);
cm.showDialog();
} catch (NoSuchElementException | WrappedTargetException | UnknownPropertyException ex) {
LOGGER.warn("Problem showing citation manager", ex);
}
});
exportCitations.addActionListener(event -> exportEntries());
selectDocument.setEnabled(false);
pushEntries.setEnabled(false);
pushEntriesInt.setEnabled(false);
pushEntriesEmpty.setEnabled(false);
pushEntriesAdvanced.setEnabled(false);
update.setEnabled(false);
merge.setEnabled(false);
manageCitations.setEnabled(false);
exportCitations.setEnabled(false);
diag = new JDialog((JFrame) null, "OpenOffice/LibreOffice panel", false);
FormBuilder mainBuilder = FormBuilder.create()
.layout(new FormLayout("fill:pref:grow", "p,p,p,p,p,p,p,p,p,p,p"));
FormBuilder topRowBuilder = FormBuilder.create()
.layout(new FormLayout(
"fill:pref:grow, 1dlu, fill:pref:grow, 1dlu, fill:pref:grow, 1dlu, fill:pref:grow, 1dlu, fill:pref",
"pref"));
topRowBuilder.add(connect).xy(1, 1);
topRowBuilder.add(manualConnect).xy(3, 1);
topRowBuilder.add(selectDocument).xy(5, 1);
topRowBuilder.add(update).xy(7, 1);
topRowBuilder.add(help).xy(9, 1);
mainBuilder.add(topRowBuilder.getPanel()).xy(1, 1);
mainBuilder.add(setStyleFile).xy(1, 2);
mainBuilder.add(pushEntries).xy(1, 3);
mainBuilder.add(pushEntriesInt).xy(1, 4);
mainBuilder.add(pushEntriesAdvanced).xy(1, 5);
mainBuilder.add(pushEntriesEmpty).xy(1, 6);
mainBuilder.add(merge).xy(1, 7);
mainBuilder.add(manageCitations).xy(1, 8);
mainBuilder.add(exportCitations).xy(1, 9);
mainBuilder.add(settingsB).xy(1, 10);
JPanel content = new JPanel();
sidePane.setContentContainer(content);
content.setLayout(new BorderLayout());
content.add(mainBuilder.getPanel(), BorderLayout.CENTER);
frame.getTabbedPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(Globals.getKeyPrefs().getKey(KeyBinding.REFRESH_OO), "Refresh OO");
frame.getTabbedPane().getActionMap().put("Refresh OO", updateAction);
}
private void exportEntries() {
try {
if (style == null) {
style = loader.getUsedStyle();
} else {
style.ensureUpToDate();
}
ooBase.updateSortedReferenceMarks();
List<BibDatabase> databases = getBaseList();
List<String> unresolvedKeys = ooBase.refreshCiteMarkers(databases, style);
BibDatabase newDatabase = ooBase.generateDatabase(databases);
if (!unresolvedKeys.isEmpty()) {
JOptionPane.showMessageDialog(frame,
Localization.lang(
"Your OpenOffice/LibreOffice document references the BibTeX key '%0', which could not be found in your current library.",
unresolvedKeys.get(0)),
Localization.lang("Unable to generate new library"), JOptionPane.ERROR_MESSAGE);
}
Defaults defaults = new Defaults(Globals.prefs.getDefaultBibDatabaseMode());
BibDatabaseContext databaseContext = new BibDatabaseContext(newDatabase, defaults);
this.frame.addTab(databaseContext, true);
} catch (BibEntryNotFoundException ex) {
JOptionPane.showMessageDialog(frame,
Localization.lang(
"Your OpenOffice/LibreOffice document references the BibTeX key '%0', which could not be found in your current library.",
ex.getBibtexKey()),
Localization.lang("Unable to synchronize bibliography"), JOptionPane.ERROR_MESSAGE);
LOGGER.debug("BibEntry not found", ex);
} catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException |
UndefinedCharacterFormatException | NoSuchElementException | WrappedTargetException | IOException |
CreationException e) {
LOGGER.warn("Problem generating new database.", e);
}
}
private List<BibDatabase> getBaseList() {
List<BibDatabase> databases = new ArrayList<>();
if (preferences.useAllDatabases()) {
for (BasePanel basePanel : frame.getBasePanelList()) {
databases.add(basePanel.getDatabase());
}
} else {
databases.add(frame.getCurrentBasePanel().getDatabase());
}
return databases;
}
private void connect(boolean autoDetect) {
if (autoDetect) {
DetectOpenOfficeInstallation officeInstallation = new DetectOpenOfficeInstallation(diag, preferences);
if (!officeInstallation.isInstalled()) {
JOptionPane.showMessageDialog(diag, Localization.lang("Autodetection failed"),
Localization.lang("Autodetection failed"), JOptionPane.ERROR_MESSAGE);
return;
}
diag.dispose();
} else {
showManualConnectionDialog();
if (!dialogOkPressed) {
return;
}
}
JDialog progressDialog = null;
try {
// Add OO JARs to the classpath
loadOpenOfficeJars(Paths.get(preferences.getInstallationPath()));
// Show progress dialog:
progressDialog = new DetectOpenOfficeInstallation(diag, preferences)
.showProgressDialog(diag, Localization.lang("Connecting"), Localization.lang("Please wait..."));
getWorker().run(); // Do the actual connection, using Spin to get off the EDT.
progressDialog.dispose();
diag.dispose();
if (ooBase == null) {
throw connectException;
}
if (ooBase.isConnectedToDocument()) {
frame.output(Localization.lang("Connected to document") + ": " + ooBase.getCurrentDocumentTitle().orElse(""));
}
// Enable actions that depend on Connect:
selectDocument.setEnabled(true);
pushEntries.setEnabled(true);
pushEntriesInt.setEnabled(true);
pushEntriesEmpty.setEnabled(true);
pushEntriesAdvanced.setEnabled(true);
update.setEnabled(true);
merge.setEnabled(true);
manageCitations.setEnabled(true);
exportCitations.setEnabled(true);
} catch (UnsatisfiedLinkError e) {
LOGGER.warn("Could not connect to running OpenOffice/LibreOffice", e);
JOptionPane.showMessageDialog(frame,
Localization.lang("Unable to connect. One possible reason is that JabRef "
+ "and OpenOffice/LibreOffice are not both running in either 32 bit mode or 64 bit mode."));
} catch (IOException e) {
LOGGER.warn("Could not connect to running OpenOffice/LibreOffice", e);
JOptionPane.showMessageDialog(frame,
Localization.lang("Could not connect to running OpenOffice/LibreOffice.") + "\n"
+ Localization.lang("Make sure you have installed OpenOffice/LibreOffice with Java support.") + "\n"
+ Localization.lang("If connecting manually, please verify program and library paths.")
+ "\n" + "\n" + Localization.lang("Error message:") + " " + e.getMessage());
} finally {
if (progressDialog != null) {
progressDialog.dispose();
}
}
}
private void loadOpenOfficeJars(Path configurationPath) throws IOException {
List<Optional<Path>> filePaths = OpenOfficePreferences.OO_JARS.stream().map(jar -> FileUtil.find(jar, configurationPath)).collect(Collectors.toList());
if (!filePaths.stream().allMatch(Optional::isPresent)) {
throw new IOException("(Not all) required Open Office Jars were found inside installation path.");
}
List<URL> jarURLs = new ArrayList<>(OpenOfficePreferences.OO_JARS.size());
for (Optional<Path> jarPath : filePaths) {
jarURLs.add((jarPath.get().toUri().toURL()));
}
addURL(jarURLs);
}
@Override
public void run() {
try {
// Connect
ooBase = new OOBibBase(preferences.getExecutablePath(), true);
} catch (UnknownPropertyException |
CreationException | NoSuchElementException | WrappedTargetException | IOException |
NoDocumentException | BootstrapException | InvocationTargetException | IllegalAccessException e) {
ooBase = null;
connectException = new IOException(e.getMessage());
}
}
private static void addURL(List<URL> jarList) throws IOException {
URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", (Class<?>[]) new Class[] {URL.class});
method.setAccessible(true);
for (URL anU : jarList) {
method.invoke(sysloader, anU);
}
} catch (SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
LOGGER.error("Could not add URL to system classloader", e);
throw new IOException("Error, could not add URL to system classloader", e);
}
}
private void showManualConnectionDialog() {
dialogOkPressed = false;
final JDialog cDiag = new JDialog(frame, Localization.lang("Set connection parameters"), true);
final NativeDesktop nativeDesktop = JabRefDesktop.getNativeDesktop();
final DialogService dirDialog = new FXDialogService();
DirectoryDialogConfiguration dirDialogConfiguration = new DirectoryDialogConfiguration.Builder()
.withInitialDirectory(nativeDesktop.getApplicationDirectory()).build();
FileDialogConfiguration fileDialogConfiguration = new FileDialogConfiguration.Builder()
.withInitialDirectory(nativeDesktop.getApplicationDirectory()).build();
DialogService fileDialog = new FXDialogService();
// Path fields
final JTextField ooPath = new JTextField(30);
JButton browseOOPath = new JButton(Localization.lang("Browse"));
ooPath.setText(preferences.getInstallationPath());
browseOOPath.addActionListener(e ->
DefaultTaskExecutor.runInJavaFXThread(() -> dirDialog.showDirectorySelectionDialog(dirDialogConfiguration))
.ifPresent(f -> ooPath.setText(f.toAbsolutePath().toString()))
);
final JTextField ooExec = new JTextField(30);
JButton browseOOExec = new JButton(Localization.lang("Browse"));
ooExec.setText(preferences.getExecutablePath());
browseOOExec.addActionListener(e ->
DefaultTaskExecutor.runInJavaFXThread(() -> fileDialog.showFileOpenDialog(fileDialogConfiguration))
.ifPresent(f -> ooExec.setText(f.toAbsolutePath().toString()))
);
final JTextField ooJars = new JTextField(30);
ooJars.setText(preferences.getJarsPath());
JButton browseOOJars = new JButton(Localization.lang("Browse"));
browseOOJars.addActionListener(e ->
DefaultTaskExecutor.runInJavaFXThread(() -> dirDialog.showDirectorySelectionDialog(dirDialogConfiguration))
.ifPresent(f -> ooJars.setText(f.toAbsolutePath().toString()))
);
FormBuilder builder = FormBuilder.create()
.layout(new FormLayout("left:pref, 4dlu, fill:pref:grow, 4dlu, fill:pref", "pref"));
if (OS.WINDOWS || OS.OS_X) {
builder.add(Localization.lang("Path to OpenOffice/LibreOffice directory")).xy(1, 1);
builder.add(ooPath).xy(3, 1);
builder.add(browseOOPath).xy(5, 1);
} else {
builder.add(Localization.lang("Path to OpenOffice/LibreOffice executable")).xy(1, 1);
builder.add(ooExec).xy(3, 1);
builder.add(browseOOExec).xy(5, 1);
builder.appendRows("4dlu, pref");
builder.add(Localization.lang("Path to OpenOffice/LibreOffice library dir")).xy(1, 3);
builder.add(ooJars).xy(3, 3);
builder.add(browseOOJars).xy(5, 3);
}
builder.padding("5dlu, 5dlu, 5dlu, 5dlu");
cDiag.getContentPane().add(builder.getPanel(), BorderLayout.CENTER);
// Buttons
JButton ok = new JButton(Localization.lang("OK"));
JButton cancel = new JButton(Localization.lang("Cancel"));
ok.addActionListener(e -> {
if (OS.WINDOWS || OS.OS_X) {
preferences.updateConnectionParams(ooPath.getText(), ooPath.getText(), ooPath.getText());
} else {
preferences.updateConnectionParams(ooPath.getText(), ooExec.getText(), ooJars.getText());
}
dialogOkPressed = true;
cDiag.dispose();
});
cancel.addActionListener(e -> cDiag.dispose());
ButtonBarBuilder bb = new ButtonBarBuilder();
bb.addGlue();
bb.addRelatedGap();
bb.addButton(ok);
bb.addButton(cancel);
bb.addGlue();
bb.padding("5dlu, 5dlu, 5dlu, 5dlu");
cDiag.getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
// Finish and show dirDialog
cDiag.pack();
cDiag.setLocationRelativeTo(frame);
cDiag.setVisible(true);
}
private void pushEntries(boolean inParenthesisIn, boolean withText, boolean addPageInfo) {
if (!ooBase.isConnectedToDocument()) {
JOptionPane.showMessageDialog(frame,
Localization.lang("Not connected to any Writer document. Please"
+ " make sure a document is open, and use the 'Select Writer document' button to connect to it."),
Localization.lang("Error"), JOptionPane.ERROR_MESSAGE);
return;
}
Boolean inParenthesis = inParenthesisIn;
String pageInfo = null;
if (addPageInfo) {
AdvancedCiteDialog citeDialog = new AdvancedCiteDialog(frame);
citeDialog.showDialog();
if (citeDialog.canceled()) {
return;
}
if (!citeDialog.getPageInfo().isEmpty()) {
pageInfo = citeDialog.getPageInfo();
}
inParenthesis = citeDialog.isInParenthesisCite();
}
BasePanel panel = frame.getCurrentBasePanel();
if (panel != null) {
final BibDatabase database = panel.getDatabase();
List<BibEntry> entries = panel.getSelectedEntries();
if (!entries.isEmpty() && checkThatEntriesHaveKeys(entries)) {
try {
if (style == null) {
style = loader.getUsedStyle();
}
ooBase.insertEntry(entries, database, getBaseList(), style, inParenthesis, withText, pageInfo,
preferences.syncWhenCiting());
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog(frame,
Localization
.lang("You must select either a valid style file, or use one of the default styles."),
Localization.lang("No valid style file defined"), JOptionPane.ERROR_MESSAGE);
LOGGER.warn("Problem with style file", ex);
} catch (ConnectionLostException ex) {
showConnectionLostErrorMessage();
} catch (UndefinedCharacterFormatException ex) {
reportUndefinedCharacterFormat(ex);
} catch (UndefinedParagraphFormatException ex) {
reportUndefinedParagraphFormat(ex);
} catch (com.sun.star.lang.IllegalArgumentException | UnknownPropertyException | PropertyVetoException |
CreationException | NoSuchElementException | WrappedTargetException | IOException |
BibEntryNotFoundException | IllegalTypeException | PropertyExistException |
NotRemoveableException ex) {
LOGGER.warn("Could not insert entry", ex);
}
}
}
}
/**
* Check that all entries in the list have BibTeX keys, if not ask if they should be generated
*
* @param entries A list of entries to be checked
* @return true if all entries have BibTeX keys, if it so may be after generating them
*/
private boolean checkThatEntriesHaveKeys(List<BibEntry> entries) {
// Check if there are empty keys
boolean emptyKeys = false;
for (BibEntry entry : entries) {
if (!entry.getCiteKeyOptional().isPresent()) {
// Found one, no need to look further for now
emptyKeys = true;
break;
}
}
// If no empty keys, return true
if (!emptyKeys) {
return true;
}
// Ask if keys should be generated
String[] options = {Localization.lang("Generate keys"), Localization.lang("Cancel")};
int answer = JOptionPane.showOptionDialog(this.frame,
Localization.lang("Cannot cite entries without BibTeX keys. Generate keys now?"),
Localization.lang("Cite"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options,
null);
BasePanel panel = frame.getCurrentBasePanel();
if ((answer == JOptionPane.OK_OPTION) && (panel != null)) {
// Generate keys
BibtexKeyPatternPreferences prefs = Globals.prefs.getBibtexKeyPatternPreferences();
NamedCompound undoCompound = new NamedCompound(Localization.lang("Cite"));
for (BibEntry entry : entries) {
if (!entry.getCiteKeyOptional().isPresent()) {
// Generate key
BibtexKeyPatternUtil
.makeAndSetLabel(
panel.getBibDatabaseContext().getMetaData().getCiteKeyPattern(prefs.getKeyPattern()),
panel.getDatabase(), entry,
prefs);
// Add undo change
undoCompound.addEdit(
new UndoableKeyChange(entry, null, entry.getCiteKeyOptional().get()));
}
}
undoCompound.end();
// Add all undos
panel.getUndoManager().addEdit(undoCompound);
// Now every entry has a key
return true;
} else {
// No, we canceled (or there is no panel to get the database from, highly unlikely)
return false;
}
}
private void showConnectionLostErrorMessage() {
JOptionPane.showMessageDialog(frame,
Localization.lang("Connection to OpenOffice/LibreOffice has been lost. "
+ "Please make sure OpenOffice/LibreOffice is running, and try to reconnect."),
Localization.lang("Connection lost"), JOptionPane.ERROR_MESSAGE);
}
private void reportUndefinedParagraphFormat(UndefinedParagraphFormatException ex) {
JOptionPane
.showMessageDialog(
frame, "<html>"
+ Localization.lang(
"Your style file specifies the paragraph format '%0', "
+ "which is undefined in your current OpenOffice/LibreOffice document.",
ex.getFormatName())
+ "<br>"
+ Localization
.lang("The paragraph format is controlled by the property 'ReferenceParagraphFormat' or 'ReferenceHeaderParagraphFormat' in the style file.")
+ "</html>",
"", JOptionPane.ERROR_MESSAGE);
}
private void reportUndefinedCharacterFormat(UndefinedCharacterFormatException ex) {
JOptionPane
.showMessageDialog(
frame, "<html>"
+ Localization.lang(
"Your style file specifies the character format '%0', "
+ "which is undefined in your current OpenOffice/LibreOffice document.",
ex.getFormatName())
+ "<br>"
+ Localization
.lang("The character format is controlled by the citation property 'CitationCharacterFormat' in the style file.")
+ "</html>",
"", JOptionPane.ERROR_MESSAGE);
}
private void showSettingsPopup() {
JPopupMenu menu = new JPopupMenu();
final JCheckBoxMenuItem autoSync = new JCheckBoxMenuItem(
Localization.lang("Automatically sync bibliography when inserting citations"),
preferences.syncWhenCiting());
final JRadioButtonMenuItem useActiveBase = new JRadioButtonMenuItem(
Localization.lang("Look up BibTeX entries in the active tab only"));
final JRadioButtonMenuItem useAllBases = new JRadioButtonMenuItem(
Localization.lang("Look up BibTeX entries in all open libraries"));
final JMenuItem clearConnectionSettings = new JMenuItem(Localization.lang("Clear connection settings"));
ButtonGroup bg = new ButtonGroup();
bg.add(useActiveBase);
bg.add(useAllBases);
if (preferences.useAllDatabases()) {
useAllBases.setSelected(true);
} else {
useActiveBase.setSelected(true);
}
autoSync.addActionListener(e -> preferences.setSyncWhenCiting(autoSync.isSelected()));
useAllBases.addActionListener(e -> preferences.setUseAllDatabases(useAllBases.isSelected()));
useActiveBase.addActionListener(e -> preferences.setUseAllDatabases(!useActiveBase.isSelected()));
clearConnectionSettings.addActionListener(e -> frame.output(preferences.clearConnectionSettings()));
menu.add(autoSync);
menu.addSeparator();
menu.add(useActiveBase);
menu.add(useAllBases);
menu.addSeparator();
menu.add(clearConnectionSettings);
menu.show(settingsB, 0, settingsB.getHeight());
}
public SidePaneComponent.ToggleAction getToggleAction() {
return sidePane.getToggleAction();
}
}