/* * WPCleaner: A tool to help on Wikipedia maintenance tasks. * Copyright (C) 2013 Nicolas Vervelle * * See README.txt file for licensing information. */ package org.wikipediacleaner.gui.swing.bot; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionListener; import java.beans.EventHandler; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.Set; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.JTable; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.ListSelectionModel; import javax.swing.ScrollPaneConstants; import javax.swing.SpinnerNumberModel; import javax.swing.SwingConstants; import org.wikipediacleaner.api.check.algorithm.CheckErrorAlgorithm; import org.wikipediacleaner.api.check.algorithm.CheckErrorAlgorithms; import org.wikipediacleaner.api.constants.EnumWikipedia; import org.wikipediacleaner.gui.swing.basic.BasicWindow; import org.wikipediacleaner.gui.swing.basic.Utilities; import org.wikipediacleaner.i18n.GT; import org.wikipediacleaner.images.EnumImageSize; import org.wikipediacleaner.utils.Configuration; import org.wikipediacleaner.utils.ConfigurationValueBoolean; import org.wikipediacleaner.utils.ConfigurationValueInteger; /** * A panel for Check Wiki bot tools. */ public class CWToolsPanel extends BotToolsPanel { /** Serialization */ private static final long serialVersionUID = -8468890591813838957L; /** Configure if page that couldn't be fixed should be analyzed */ private JCheckBox chkCWAnalyze; /** No limit of number of pages for non CW error */ private JCheckBox chkNoLimit; /** Configure number of pages for each error */ private SpinnerNumberModel modelNbPages; /** Comment */ private JTextField txtComment; /** Table model for Check Wiki automatic fixing */ BotCWTableModel modelCWAutomaticFixing; /** Table for Check Wiki automatic fixing */ private JTable tableCWAutomaticFixing; /** Button for loading selection */ private JButton buttonLoadSelection; /** * Construct a Check Wiki bot tools panel. * * @param window Parent window. */ public CWToolsPanel(BasicWindow window) { super(window, new GridBagLayout()); initialize(); } /** * Initialize the panel. */ private void initialize() { // Configuration Configuration config = Configuration.getConfiguration(); // Initialize constraints final int maxX = 3; GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.gridheight = 1; constraints.gridwidth = maxX; constraints.gridx = 0; constraints.gridy = 0; constraints.insets = new Insets(0, 0, 0, 0); constraints.ipadx = 0; constraints.ipady = 0; constraints.weightx = 1; constraints.weighty = 0; // Label JLabel labelCW = Utilities.createJLabel(GT._("Automatic fixing for Check Wiki")); add(labelCW, constraints); constraints.gridy++; // Table for listing errors modelCWAutomaticFixing = new BotCWTableModel(window.getWikipedia()); tableCWAutomaticFixing = new JTable(modelCWAutomaticFixing); tableCWAutomaticFixing.setRowSelectionAllowed(false); tableCWAutomaticFixing.setColumnSelectionAllowed(false); modelCWAutomaticFixing.configureColumnModel(tableCWAutomaticFixing); Utilities.addRowSorter(tableCWAutomaticFixing, modelCWAutomaticFixing); JScrollPane paneCWAutomaticFixing = new JScrollPane(tableCWAutomaticFixing); paneCWAutomaticFixing.setMinimumSize(new Dimension(200, 200)); paneCWAutomaticFixing.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); paneCWAutomaticFixing.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); constraints.weighty = 1; add(paneCWAutomaticFixing, constraints); constraints.gridy++; constraints.weighty = 0; // Explanation String txtExplanation = GT._("To use Check Wiki bot tools:") + "\n" + " - " + GT._("Select algorithms for which automatic fixing will be applied") + "\n" + " - " + GT._("Select algorithms that will be used to create a list of pages to work on") + "\n" + " - " + GT._("Run the tools below"); JTextArea lblExplanation = new JTextArea(txtExplanation); lblExplanation.setEditable(false); lblExplanation.setBackground(getBackground()); add(lblExplanation, constraints); constraints.gridy++; // Check box to decide if pages should be analyzed if not fixed chkCWAnalyze = Utilities.createJCheckBox( GT._("Analyze pages that couldn't be fixed by bot"), config.getBoolean(null, ConfigurationValueBoolean.CHECK_BOT_ANALYZE)); add(chkCWAnalyze, constraints); constraints.gridy++; // No limit for number of errors chkNoLimit = Utilities.createJCheckBox( GT._("Ignore limit for errors not on Labs"), false); add(chkNoLimit, constraints); constraints.gridy++; // Number of errors modelNbPages = new SpinnerNumberModel( config.getInt(null, ConfigurationValueInteger.CHECK_BOT_NB_PAGES), 1, 10000, 1); JSpinner spinNbPages = new JSpinner(modelNbPages); JLabel labelNbPages = Utilities.createJLabel(GT._("Number of pages:")); labelNbPages.setLabelFor(spinNbPages); constraints.gridwidth = 2; constraints.weightx = 1; add(labelNbPages, constraints); constraints.gridx += constraints.gridwidth; constraints.gridwidth = maxX - constraints.gridwidth; constraints.weightx = 0; add(spinNbPages, constraints); constraints.gridx = 0; constraints.gridy++; // Comment txtComment = Utilities.createJTextField("", 40); JLabel labelComment = Utilities.createJLabel(GT._("Comment:")); labelComment.setLabelFor(txtComment); constraints.gridwidth = 1; constraints.weightx = 0; add(labelComment, constraints); constraints.gridx += constraints.gridwidth; constraints.gridwidth = maxX - constraints.gridwidth; constraints.weightx = 1; add(txtComment, constraints); constraints.gridx = 0; constraints.gridy++; // Buttons JToolBar toolbarButtons = new JToolBar(SwingConstants.HORIZONTAL); toolbarButtons.setFloatable(false); // Button for running the automatic fixing JButton buttonCWAutomaticFixing = Utilities.createJButton( "commons-nuvola-web-broom.png", EnumImageSize.NORMAL, GT._("Automatic fixing for Check Wiki"), false, null); buttonCWAutomaticFixing.addActionListener(EventHandler.create( ActionListener.class, this, "actionCWAutomaticFixing")); toolbarButtons.add(buttonCWAutomaticFixing); // Button for marking errors already fixed JButton buttonCWAutomaticMarking = Utilities.createJButton( "gnome-dialog-apply.png", EnumImageSize.NORMAL, GT._("Mark errors already fixed"), false, null); buttonCWAutomaticMarking.addActionListener(EventHandler.create( ActionListener.class, this, "actionCWAutomaticMarking")); toolbarButtons.add(buttonCWAutomaticMarking); // Button for checking white lists JButton buttonCWCheckWhiteLists = Utilities.createJButton( "gnome-edit-find.png", EnumImageSize.NORMAL, GT._("Check whitelists"), false, null); buttonCWCheckWhiteLists.addActionListener(EventHandler.create( ActionListener.class, this, "actionCWCheckWhiteLists")); toolbarButtons.add(buttonCWCheckWhiteLists); // Button for listing errors from dump file JButton buttonListCW = Utilities.createJButton( "gnome-logviewer.png", EnumImageSize.NORMAL, GT._("Analyze dump file"), false, null); buttonListCW.addActionListener(EventHandler.create( ActionListener.class, this, "actionCWLists")); toolbarButtons.add(buttonListCW); // Button for saving selection JButton buttonSaveSelection = Utilities.createJButton( "gnome-document-save.png", EnumImageSize.NORMAL, GT._("Save selection"), false, null); buttonSaveSelection.addActionListener(EventHandler.create( ActionListener.class, this, "actionSaveSelection")); toolbarButtons.add(buttonSaveSelection); // Button for loading selection buttonLoadSelection = Utilities.createJButton( "gnome-drive-harddisk.png", EnumImageSize.NORMAL, GT._("Load selection"), false, null); buttonLoadSelection.addActionListener(EventHandler.create( ActionListener.class, this, "actionLoadSelection")); toolbarButtons.add(buttonLoadSelection); constraints.gridwidth = maxX; constraints.weightx = 1; add(toolbarButtons, constraints); constraints.gridy++; // Select errors that can be fixed by bot ListSelectionModel selectionModel = tableCWAutomaticFixing.getSelectionModel(); selectionModel.clearSelection(); } /** * Action called when Automatic Check Wiki Fixing button is pressed. */ public void actionCWAutomaticFixing() { automaticFixing(true); } /** * Action called when Automatic Check Wiki Marking button is pressed. */ public void actionCWAutomaticMarking() { automaticFixing(false); } /** * @param saveModifications True if modifications should be saved. */ private void automaticFixing(boolean saveModifications) { EnumWikipedia wiki = window.getWikipedia(); if (!wiki.getCWConfiguration().isProjectAvailable()) { Utilities.displayMissingConfiguration( window.getParentComponent(), null); return; } List<CheckErrorAlgorithm> fixAlgorithms = modelCWAutomaticFixing.getFixAlgorithms(); if ((fixAlgorithms == null) || fixAlgorithms.isEmpty()) { window.displayWarning(GT._("You must select at least one algorithm for fixing errors")); return; } List<CheckErrorAlgorithm> listAlgorithms = modelCWAutomaticFixing.getListAlgorithms(); if ((listAlgorithms == null) || listAlgorithms.isEmpty()) { window.displayWarning(GT._("You must select at least one algorithm for listing errors")); return; } int answer = window.displayYesNoWarning(BasicWindow.experimentalMessage); if (answer != JOptionPane.YES_OPTION) { return; } int max = 100; if (modelNbPages.getNumber() != null) { Number number = modelNbPages.getNumber(); max = number.intValue(); } Configuration config = Configuration.getConfiguration(); boolean analyze = false; if (saveModifications) { analyze = chkCWAnalyze.isSelected(); config.setBoolean(null, ConfigurationValueBoolean.CHECK_BOT_ANALYZE, analyze); } boolean noLimit = chkNoLimit.isSelected(); config.setInt(null, ConfigurationValueInteger.CHECK_BOT_NB_PAGES, max); AutomaticCWWorker worker = new AutomaticCWWorker( wiki, window, listAlgorithms, max, noLimit, fixAlgorithms, txtComment.getText(), saveModifications, analyze); worker.start(); } /** * Action called when Check White Lists button is pressed. */ public void actionCWCheckWhiteLists() { EnumWikipedia wiki = window.getWikipedia(); CWCheckWhiteListsWorker worker = new CWCheckWhiteListsWorker(wiki, window); worker.start(); } /** * Action called when List Check Wiki errors button is pressed. */ public void actionCWLists() { EnumWikipedia wiki = window.getWikipedia(); if (!wiki.getCWConfiguration().isProjectAvailable()) { Utilities.displayMissingConfiguration( window.getParentComponent(), null); return; } List<CheckErrorAlgorithm> listAlgorithms = modelCWAutomaticFixing.getListAlgorithms(); if ((listAlgorithms == null) || listAlgorithms.isEmpty()) { window.displayWarning(GT._("You must select at least one algorithm for listing errors")); return; } int answer = window.displayYesNoWarning(BasicWindow.experimentalMessage); if (answer != JOptionPane.YES_OPTION) { return; } boolean done = false; File dumpFile = null; boolean exportWiki = false; File outputDir = null; String exportPage = null; boolean checkWiki = false; boolean onlyRecheck = false; while (!done) { ListCWPanel panel = new ListCWPanel(wiki); int result = JOptionPane.showConfirmDialog( window.getParentComponent(), panel, GT._("Analyze dump file"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); if (result != JOptionPane.OK_OPTION) { return; } dumpFile = panel.getDumpFile(); exportWiki = panel.exportOnWiki(); outputDir = panel.getExportDir(); exportPage = panel.getExportPage(); checkWiki = panel.checkWiki(); onlyRecheck = panel.onlyRecheck(); if ((dumpFile != null) && ((exportWiki && (exportPage != null)) || (!exportWiki && (outputDir != null)))) { done = true; panel.saveConfiguration(); } } ListCWWorker worker = null; if (exportWiki) { worker = new ListCWWorker( wiki, window, dumpFile, exportPage, listAlgorithms, checkWiki, onlyRecheck); } else { worker = new ListCWWorker( wiki, window, dumpFile, outputDir, listAlgorithms, checkWiki); } worker.start(); } /** * Action called when Save Selection button is pressed. */ public void actionSaveSelection() { // Retrieve configuration name String name = window.askForValue(GT._("What is the name of the selection?"), null, null); if ((name == null) || (name.isEmpty())) { return; } // Create a string representing the current selection StringBuilder buffer = new StringBuilder(); List<CheckErrorAlgorithm> algorithms = modelCWAutomaticFixing.getFixAlgorithms(); if (algorithms != null) { for (int i = 0; i < algorithms.size(); i++) { if (i > 0) { buffer.append(","); } buffer.append(algorithms.get(i).getErrorNumber()); } } buffer.append("|"); algorithms = modelCWAutomaticFixing.getListAlgorithms(); if (algorithms != null) { for (int i = 0; i < algorithms.size(); i++) { if (i > 0) { buffer.append(","); } buffer.append(algorithms.get(i).getErrorNumber()); } } // Save configuration Configuration config = Configuration.getConfiguration(); config.setSubString(null, Configuration.ARRAY_CHECK_BOT_SELECTION, name, buffer.toString()); } /** * Action called when Load Selection button is pressed. */ public void actionLoadSelection() { // Retrieve possible selections Configuration config = Configuration.getConfiguration(); Properties properties = config.getProperties(null, Configuration.ARRAY_CHECK_BOT_SELECTION); if ((properties == null) || (properties.isEmpty())) { return; } Set<Object> keySet = properties.keySet(); List<String> keyList = new ArrayList<String>(); for (Object key : keySet) { keyList.add(key.toString()); } Collections.sort(keyList); // Create menu JPopupMenu menu = new JPopupMenu(); for (String name : keyList) { JMenuItem item = Utilities.createJMenuItem(name, true); item.setActionCommand(properties.getProperty(name)); item.addActionListener(EventHandler.create( ActionListener.class, this, "actionLoadSelection", "actionCommand")); menu.add(item); } menu.show( buttonLoadSelection, 0, buttonLoadSelection.getHeight()); } /** * Action called when Load Selection menu item is selected. * * @param selection Selection. */ public void actionLoadSelection(String selection) { if (selection == null) { return; } String[] parts = selection.split("\\|"); List<CheckErrorAlgorithm> algorithms = new ArrayList<CheckErrorAlgorithm>(); if ((parts != null) && (parts.length > 0)) { String[] elements = parts[0].split("\\,"); for (int i = 0; i < elements.length; i++) { try { int errorNumber = Integer.parseInt(elements[i]); CheckErrorAlgorithm algorithm = CheckErrorAlgorithms.getAlgorithm( window.getWiki(), errorNumber); if (algorithm != null) { algorithms.add(algorithm); } } catch (NumberFormatException e) { // } } } modelCWAutomaticFixing.setFixAlgorithms(algorithms); algorithms.clear(); if ((parts != null) && (parts.length > 1)) { String[] elements = parts[1].split("\\,"); for (int i = 0; i < elements.length; i++) { try { int errorNumber = Integer.parseInt(elements[i]); CheckErrorAlgorithm algorithm = CheckErrorAlgorithms.getAlgorithm( window.getWiki(), errorNumber); if (algorithm != null) { algorithms.add(algorithm); } } catch (NumberFormatException e) { // } } } modelCWAutomaticFixing.setListAlgorithms(algorithms); } }