package org.jabref.gui.actions; import java.awt.event.ActionEvent; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.RowFilter; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import org.jabref.Globals; import org.jabref.gui.JabRefFrame; import org.jabref.gui.keyboard.KeyBinding; import org.jabref.logic.integrity.IntegrityCheck; import org.jabref.logic.integrity.IntegrityMessage; import org.jabref.logic.l10n.Localization; import com.jgoodies.forms.builder.FormBuilder; import com.jgoodies.forms.layout.FormLayout; public class IntegrityCheckAction extends MnemonicAwareAction { private static final String ELLIPSES = "..."; private final JabRefFrame frame; public IntegrityCheckAction(JabRefFrame frame) { this.frame = frame; putValue(Action.NAME, Localization.menuTitle("Check integrity") + ELLIPSES); putValue(Action.ACCELERATOR_KEY, Globals.getKeyPrefs().getKey(KeyBinding.CHECK_INTEGRITY)); } @Override public void actionPerformed(ActionEvent e) { IntegrityCheck check = new IntegrityCheck(frame.getCurrentBasePanel().getBibDatabaseContext(), Globals.prefs.getFileDirectoryPreferences(), Globals.prefs.getBibtexKeyPatternPreferences(), Globals.journalAbbreviationLoader .getRepository(Globals.prefs.getJournalAbbreviationPreferences())); List<IntegrityMessage> messages = check.checkBibtexDatabase(); if (messages.isEmpty()) { JOptionPane.showMessageDialog(frame.getCurrentBasePanel(), Localization.lang("No problems found.")); } else { Map<String, Boolean> showMessage = new HashMap<>(); // prepare data model Object[][] model = new Object[messages.size()][4]; int i = 0; for (IntegrityMessage message : messages) { model[i][0] = message.getEntry().getId(); model[i][1] = message.getEntry().getCiteKeyOptional().orElse(""); model[i][2] = message.getFieldName(); model[i][3] = message.getMessage(); showMessage.put(message.getMessage(), true); i++; } // construct view JTable table = new JTable(model, new Object[] {"ID", Localization.lang("BibTeX key"), Localization.lang("Field"), Localization.lang("Message")}); // hide IDs TableColumnModel columnModel = table.getColumnModel(); columnModel.removeColumn(columnModel.getColumn(0)); RowFilter<Object, Object> filter = new RowFilter<Object, Object>() { @Override public boolean include(Entry<?, ?> entry) { return showMessage.get(entry.getStringValue(3)); } }; TableRowSorter<TableModel> sorter = new TableRowSorter<>(table.getModel()); sorter.setRowFilter(filter); table.setRowSorter(sorter); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setDefaultEditor(Object.class, null); ListSelectionModel selectionModel = table.getSelectionModel(); selectionModel.addListSelectionListener(event -> { if (!event.getValueIsAdjusting()) { try { String entryId = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][0]; String fieldName = (String) model[table.convertRowIndexToModel(table.getSelectedRow())][2]; frame.getCurrentBasePanel().editEntryByIdAndFocusField(entryId, fieldName); } catch (ArrayIndexOutOfBoundsException exception) { // Ignore -- most likely caused by filtering out the earlier selected row } } }); // BibTeX key table.getColumnModel().getColumn(0).setPreferredWidth(100); // field name table.getColumnModel().getColumn(1).setPreferredWidth(60); // message table.getColumnModel().getColumn(2).setPreferredWidth(400); table.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN); JScrollPane scrollPane = new JScrollPane(table); String title = Localization.lang("%0 problem(s) found", String.valueOf(messages.size())); JDialog dialog = new JDialog(frame, title, false); JPopupMenu menu = new JPopupMenu(); for (String messageString : showMessage.keySet()) { JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(messageString, true); menuItem.addActionListener(event -> { showMessage.put(messageString, menuItem.isSelected()); ((AbstractTableModel) table.getModel()).fireTableDataChanged(); }); menu.add(menuItem); } JButton menuButton = new JButton(Localization.lang("Filter")); menuButton.addActionListener(entry -> menu.show(menuButton, 0, menuButton.getHeight())); FormBuilder builder = FormBuilder.create() .layout(new FormLayout("fill:pref:grow", "fill:pref:grow, 2dlu, pref")); builder.add(scrollPane).xy(1, 1); builder.add(menuButton).xy(1, 3, "c, b"); dialog.add(builder.getPanel()); dialog.setSize(600, 600); // show view dialog.setVisible(true); } } }