package org.jabref.gui.dbproperties; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.nio.charset.Charset; import java.util.Optional; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.DefaultComboBoxModel; import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JRadioButton; 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.JabRefDialog; import org.jabref.gui.SaveOrderConfigDisplay; import org.jabref.gui.cleanup.FieldFormatterCleanupsPanel; import org.jabref.gui.help.HelpAction; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.gui.util.DefaultTaskExecutor; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.logic.cleanup.Cleanups; import org.jabref.logic.help.HelpFile; import org.jabref.logic.l10n.Encodings; import org.jabref.logic.l10n.Localization; import org.jabref.model.database.DatabaseLocation; import org.jabref.model.metadata.MetaData; import org.jabref.model.metadata.SaveOrderConfig; import org.jabref.preferences.JabRefPreferences; import com.jgoodies.forms.builder.ButtonBarBuilder; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; public class DatabasePropertiesDialog extends JabRefDialog { private MetaData metaData; private BasePanel panel; private final JComboBox<Charset> encoding; private final JButton ok; private final JButton cancel; private final JTextField fileDir = new JTextField(40); private final JTextField fileDirIndv = new JTextField(40); private String oldFileVal = ""; private String oldFileIndvVal = ""; private SaveOrderConfig oldSaveOrderConfig; /* The code for "Save sort order" is copied from ExportSortingPrefsTab and slightly updated to fit storing at metadata */ private JRadioButton saveInOriginalOrder; private JRadioButton saveInSpecifiedOrder; private final JCheckBox protect = new JCheckBox( Localization.lang("Refuse to save the library before external changes have been reviewed.")); private boolean oldProtectVal; private SaveOrderConfigDisplay saveOrderPanel; private FieldFormatterCleanupsPanel fieldFormatterCleanupsPanel; public DatabasePropertiesDialog(JFrame parent) { super(parent, Localization.lang("Library properties"), true, DatabasePropertiesDialog.class); encoding = new JComboBox<>(); encoding.setModel(new DefaultComboBoxModel<>(Encodings.ENCODINGS)); ok = new JButton(Localization.lang("OK")); cancel = new JButton(Localization.lang("Cancel")); init(); } public void setPanel(BasePanel panel) { this.panel = panel; this.metaData = panel.getBibDatabaseContext().getMetaData(); } public void updateEnableStatus() { DatabaseLocation location = panel.getBibDatabaseContext().getLocation(); boolean isShared = (location == DatabaseLocation.SHARED); encoding.setEnabled(!isShared); // the encoding of shared database is always UTF-8 saveInOriginalOrder.setEnabled(!isShared); saveInSpecifiedOrder.setEnabled(!isShared); saveOrderPanel.setEnabled(!isShared); protect.setEnabled(!isShared); } private void init() { DirectoryDialogConfiguration directoryDialogConfiguration = new DirectoryDialogConfiguration.Builder() .withInitialDirectory(Globals.prefs.get(JabRefPreferences.WORKING_DIRECTORY)).build(); DialogService ds = new FXDialogService(); JButton browseFile = new JButton(Localization.lang("Browse")); JButton browseFileIndv = new JButton(Localization.lang("Browse")); browseFile.addActionListener(e -> DefaultTaskExecutor .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(directoryDialogConfiguration)) .ifPresent(f -> fileDir.setText(f.toAbsolutePath().toString()))); browseFileIndv.addActionListener(e -> DefaultTaskExecutor .runInJavaFXThread(() -> ds.showDirectorySelectionDialog(directoryDialogConfiguration)) .ifPresent(f -> fileDirIndv.setText(f.toAbsolutePath().toString()))); setupSortOrderConfiguration(); FormLayout form = new FormLayout("left:pref, 4dlu, pref:grow, 4dlu, pref:grow, 4dlu, pref", "pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, pref, 2dlu, fill:pref:grow, 180dlu, fill:pref:grow,"); FormBuilder builder = FormBuilder.create().layout(form); builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); builder.add(Localization.lang("Library encoding")).xy(1, 1); builder.add(encoding).xy(3, 1); builder.addSeparator(Localization.lang("Override default file directories")).xyw(1, 3, 5); builder.add(Localization.lang("General file directory")).xy(1, 5); builder.add(fileDir).xy(3, 5); builder.add(browseFile).xy(5, 5); builder.add(Localization.lang("User-specific file directory")).xy(1, 7); builder.add(fileDirIndv).xy(3, 7); builder.add(browseFileIndv).xy(5, 7); builder.addSeparator(Localization.lang("Save sort order")).xyw(1, 13, 5); builder.add(saveInOriginalOrder).xyw(1, 15, 5); builder.add(saveInSpecifiedOrder).xyw(1, 17, 5); saveOrderPanel = new SaveOrderConfigDisplay(); builder.add(saveOrderPanel.getPanel()).xyw(1, 21, 5); builder.addSeparator(Localization.lang("Library protection")).xyw(1, 23, 5); builder.add(protect).xyw(1, 25, 5); fieldFormatterCleanupsPanel = new FieldFormatterCleanupsPanel(Localization.lang("Enable save actions"), Cleanups.DEFAULT_SAVE_ACTIONS); builder.addSeparator(Localization.lang("Save actions")).xyw(1, 27, 5); builder.add(fieldFormatterCleanupsPanel).xyw(1, 29, 5); ButtonBarBuilder bb = new ButtonBarBuilder(); bb.addGlue(); bb.addButton(ok); bb.addButton(cancel); bb.addRelatedGap(); bb.addButton(new HelpAction(HelpFile.DATABASE_PROPERTIES).getHelpButton()); bb.addGlue(); bb.getPanel().setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); getContentPane().add(builder.getPanel(), BorderLayout.CENTER); getContentPane().add(bb.getPanel(), BorderLayout.SOUTH); pack(); AbstractAction closeAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { dispose(); } }; ActionMap am = builder.getPanel().getActionMap(); InputMap im = builder.getPanel().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); im.put(Globals.getKeyPrefs().getKey(KeyBinding.CLOSE_DIALOG), "close"); am.put("close", closeAction); ok.addActionListener(e -> { storeSettings(); dispose(); }); cancel.addActionListener(e -> dispose()); } private void setupSortOrderConfiguration() { saveInOriginalOrder = new JRadioButton(Localization.lang("Save entries in their original order")); saveInSpecifiedOrder = new JRadioButton(Localization.lang("Save entries ordered as specified")); ButtonGroup bg = new ButtonGroup(); bg.add(saveInOriginalOrder); bg.add(saveInSpecifiedOrder); ActionListener listener = e -> { boolean selected = e.getSource() == saveInSpecifiedOrder; saveOrderPanel.setEnabled(selected); }; saveInOriginalOrder.addActionListener(listener); saveInSpecifiedOrder.addActionListener(listener); } @Override public void setVisible(boolean visible) { if (visible) { setValues(); } super.setVisible(visible); } private void setValues() { Optional<Charset> charset = panel.getBibDatabaseContext().getMetaData().getEncoding(); encoding.setSelectedItem(charset.orElse(Globals.prefs.getDefaultEncoding())); Optional<SaveOrderConfig> storedSaveOrderConfig = metaData.getSaveOrderConfig(); boolean selected; if (!storedSaveOrderConfig.isPresent()) { saveInOriginalOrder.setSelected(true); oldSaveOrderConfig = SaveOrderConfig.getDefaultSaveOrder(); selected = false; } else { SaveOrderConfig saveOrderConfig = storedSaveOrderConfig.get(); oldSaveOrderConfig = saveOrderConfig; if (saveOrderConfig.saveInOriginalOrder) { saveInOriginalOrder.setSelected(true); selected = false; } else { saveInSpecifiedOrder.setSelected(true); selected = true; } saveOrderPanel.setSaveOrderConfig(saveOrderConfig); } saveOrderPanel.setEnabled(selected); Optional<String> fileD = metaData.getDefaultFileDirectory(); if (fileD.isPresent()) { fileDir.setText(fileD.get().trim()); } else { fileDir.setText(""); } String fileDI = metaData.getUserFileDirectory(Globals.prefs.getUser()).orElse(""); // File dir setting fileDirIndv.setText(fileDI); oldFileIndvVal = fileDirIndv.getText(); protect.setSelected(metaData.isProtected()); // Store original values to see if they get changed: oldFileVal = fileDir.getText(); oldProtectVal = protect.isSelected(); //set save actions fieldFormatterCleanupsPanel.setValues(metaData); } private void storeSettings() { Charset oldEncoding = panel.getBibDatabaseContext().getMetaData().getEncoding() .orElse(Globals.prefs.getDefaultEncoding()); Charset newEncoding = (Charset) encoding.getSelectedItem(); panel.getBibDatabaseContext().getMetaData().setEncoding(newEncoding); String text = fileDir.getText().trim(); if (text.isEmpty()) { metaData.clearDefaultFileDirectory(); } else { metaData.setDefaultFileDirectory(text); } // Repeat for individual file dir - reuse 'text' and 'dir' vars text = fileDirIndv.getText(); if (text.isEmpty()) { metaData.clearUserFileDirectory(Globals.prefs.getUser()); } else { metaData.setUserFileDirectory(Globals.prefs.getUser(), text); } if (protect.isSelected()) { metaData.markAsProtected(); } else { metaData.markAsNotProtected(); } SaveOrderConfig newSaveOrderConfig; if (saveInOriginalOrder.isSelected()) { newSaveOrderConfig = SaveOrderConfig.getDefaultSaveOrder(); } else { newSaveOrderConfig = saveOrderPanel.getSaveOrderConfig(); newSaveOrderConfig.setSaveInSpecifiedOrder(); } // See if any of the values have been modified: boolean saveOrderConfigChanged; if (newSaveOrderConfig.equals(oldSaveOrderConfig)) { saveOrderConfigChanged = false; } else { saveOrderConfigChanged = true; } if (saveOrderConfigChanged) { if (newSaveOrderConfig.equals(SaveOrderConfig.getDefaultSaveOrder())) { metaData.clearSaveOrderConfig(); } else { metaData.setSaveOrderConfig(newSaveOrderConfig); } } boolean saveActionsChanged = fieldFormatterCleanupsPanel.hasChanged(); if (saveActionsChanged) { if (fieldFormatterCleanupsPanel.isDefaultSaveActions()) { metaData.clearSaveActions(); } else { fieldFormatterCleanupsPanel.storeSettings(metaData); } } boolean changed = saveOrderConfigChanged || !newEncoding.equals(oldEncoding) || !oldFileVal.equals(fileDir.getText()) || !oldFileIndvVal.equals(fileDirIndv.getText()) || (oldProtectVal != protect.isSelected()) || saveActionsChanged; // ... if so, mark base changed. Prevent the Undo button from removing // change marking: if (changed) { panel.markNonUndoableBaseChanged(); } } }