001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.geoimage;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.io.IOException;
008import java.util.ArrayList;
009import java.util.List;
010
011import javax.xml.parsers.ParserConfigurationException;
012import javax.xml.xpath.XPathExpressionException;
013
014import org.openstreetmap.josm.actions.JosmAction;
015import org.openstreetmap.josm.data.Bounds;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.PleaseWaitRunnable;
018import org.openstreetmap.josm.io.OsmTransferException;
019import org.openstreetmap.josm.tools.Logging;
020import org.openstreetmap.josm.tools.Mediawiki;
021import org.xml.sax.SAXException;
022
023/**
024 * Loads geocoded images from <a href="https://commons.wikimedia.org/">Wikimedia Commons</a> for the given bounding box.
025 */
026public class WikimediaCommonsLoader extends PleaseWaitRunnable {
027    protected String apiUrl = "https://commons.wikimedia.org/w/api.php";
028    protected GeoImageLayer layer;
029    private final Bounds bounds;
030
031    /**
032     * Constructs a new {@code WikimediaCommonsLoader}
033     * @param bounds The bounds to load
034     */
035    public WikimediaCommonsLoader(Bounds bounds) {
036        super(tr("Load images from Wikimedia Commons"));
037        this.bounds = bounds;
038    }
039
040    @Override
041    protected void realRun() throws SAXException, IOException, OsmTransferException {
042        List<ImageEntry> imageEntries = new ArrayList<>();
043        try {
044            new Mediawiki(apiUrl).searchGeoImages(bounds, (title, latLon) -> imageEntries.add(new WikimediaCommonsEntry(title, latLon)));
045        } catch (ParserConfigurationException | XPathExpressionException e) {
046            throw new IllegalStateException(e);
047        }
048        Logging.info("Loaded {0} images from Wikimedia Commons", imageEntries.size());
049        layer = new WikimediaCommonsLayer(imageEntries);
050    }
051
052    @Override
053    protected void finish() {
054        if (layer != null) {
055            MainApplication.getLayerManager().addLayer(layer);
056        }
057    }
058
059    @Override
060    protected void cancel() {
061        // do nothing
062    }
063
064    /**
065     * Load images from Wikimedia Commons
066     * @since 18021
067     */
068    public static class WikimediaCommonsLoadImagesAction extends JosmAction {
069        /**
070         * Constructs a new {@code WikimediaCommonsLoadImagesAction}
071         */
072        public WikimediaCommonsLoadImagesAction() {
073            super(tr("Load images from Wikimedia Commons"), "wikimedia_commons", null, null, false);
074        }
075
076        @Override
077        public void actionPerformed(ActionEvent e) {
078            Bounds bounds = MainApplication.getMap().mapView.getRealBounds();
079            MainApplication.worker.execute(new WikimediaCommonsLoader(bounds));
080        }
081
082        @Override
083        protected void updateEnabledState() {
084            setEnabled(MainApplication.isDisplayingMapView());
085        }
086    }
087}