Commit d0bf68be authored by Florian Schäfer's avatar Florian Schäfer

Display the statements of a Wikidata item in the WikidataInfoToggleDialog

parent c41e6a58
Pipeline #27435976 passed with stages
in 15 minutes and 42 seconds
......@@ -10,7 +10,7 @@ public final class Caches {
public static final CacheAccess<String, String> API_RESPONSES = JCSCacheManager.getCache(
"api",
1,
1_000,
10_000,
new File(Config.getDirs().getCacheDirectory(false), "plugin/wikipedia").getAbsolutePath()
);
......
package org.wikipedia.gui;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
public class ProgressJPanel extends JPanel {
private final JProgressBar PROGRESS_BAR = new JProgressBar();
ProgressJPanel() {
setLayout(new BorderLayout());
PROGRESS_BAR.setStringPainted(true);
}
protected synchronized void showProgress(final String message) {
if (!isAncestorOf(PROGRESS_BAR)) {
add(PROGRESS_BAR, BorderLayout.NORTH);
}
PROGRESS_BAR.setIndeterminate(true);
PROGRESS_BAR.setString(message);
revalidate();
repaint();
}
protected synchronized void hideProgress() {
remove(PROGRESS_BAR);
revalidate();
repaint();
}
}
package org.wikipedia.gui;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.io.IOException;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.tools.I18n;
import org.wikipedia.WikipediaPlugin;
import org.wikipedia.api.ApiQueryClient;
import org.wikipedia.api.wikidata_action.WikidataActionApiQuery;
import org.wikipedia.api.wikidata_action.json.WbgetclaimsResult;
class WikidataInfoClaimPanel extends ProgressJPanel {
private final JPanel mainPanel;
private String qIdBeingDownloaded;
WikidataInfoClaimPanel() {
super();
this.mainPanel = new JPanel();
add(new JScrollPane(mainPanel), BorderLayout.CENTER);
}
void downloadStatementsFor(final String qId) {
this.qIdBeingDownloaded = qId;
new Thread(() -> {
try {
mainPanel.removeAll();
showProgress(I18n.tr("Download statements for {0}…", qId));
final WbgetclaimsResult result = ApiQueryClient.query(WikidataActionApiQuery.wbgetclaims(qId));
if (qIdBeingDownloaded != null && qIdBeingDownloaded.equals(qId)) {
synchronized (mainPanel) {
mainPanel.removeAll();
mainPanel.setLayout(new GridLayout(result.getClaims().size(), 1));
result.getClaims().forEach(claim -> {
final WbgetclaimsResult.Claim.MainSnak.DataValue value = claim.getMainSnak().getDataValue(); // nullable
mainPanel.add(new StatementPanel(claim.getMainSnak().getProperty(), value == null ? I18n.tr("Unknown datatype!") : value.toString()));
});
hideProgress();
}
}
} catch (IOException e) {
new Notification(I18n.tr("Failed to download statements for Wikidata item {0}!", qId))
.setIcon(WikipediaPlugin.W_IMAGE.get())
.show();
}
hideProgress();
}).start();
}
}
......@@ -4,15 +4,16 @@ import java.awt.BorderLayout;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.tools.I18n;
import org.openstreetmap.josm.tools.Logging;
import org.openstreetmap.josm.tools.Pair;
import org.wikipedia.WikipediaPlugin;
import org.wikipedia.api.ApiQueryClient;
......@@ -22,42 +23,18 @@ import org.wikipedia.api.wikidata_action.json.WbgetentitiesResult;
/**
* Panel displaying the labels for a Wikidata item
*/
class WikidataInfoLabelPanel extends JPanel {
private static final JProgressBar downloadProgress = new JProgressBar();
class WikidataInfoLabelPanel extends ProgressJPanel {
private final LabelTableModel tableModel = new LabelTableModel(this);
static {
downloadProgress.setStringPainted(true);
}
private final JTable table = new JTable(tableModel);
WikidataInfoLabelPanel() {
setLayout(new BorderLayout());
add(new JTable(tableModel), BorderLayout.CENTER);
}
void clear() {
tableModel.clear();
add(new JScrollPane(table), BorderLayout.CENTER);
}
void downloadLabelsFor(final String qId) {
tableModel.downloadLabelsFor(qId);
}
private synchronized void showDownloadProgress(final String qId) {
if (!isAncestorOf(downloadProgress)) {
add(downloadProgress, BorderLayout.NORTH);
}
downloadProgress.setIndeterminate(true);
downloadProgress.setString(I18n.tr("Download labels for {0}…", qId));
revalidate();
}
private synchronized void hideDownloadProgress() {
remove(downloadProgress);
revalidate();
}
private static class LabelTableModel extends AbstractTableModel {
private final WikidataInfoLabelPanel parent;
private String qIdBeingDownloaded;
......@@ -67,36 +44,40 @@ class WikidataInfoLabelPanel extends JPanel {
this.parent = parent;
}
void clear() {
this.valueMap.clear();
}
void downloadLabelsFor(final String qId) {
synchronized (valueMap) {
qIdBeingDownloaded = qId;
parent.showDownloadProgress(qId);
}
qIdBeingDownloaded = qId;
new Thread(() -> {
try {
parent.showProgress(I18n.tr("Download labels for {0}…", qId));
valueMap.clear();
parent.table.revalidate();
parent.revalidate();
parent.repaint();
final Map<String, WbgetentitiesResult.Entity.Label> newValues = ApiQueryClient.query(WikidataActionApiQuery.wbgetentitiesLabels(qId));
final Map<String, String> languages = new HashMap<>();
try {
languages.putAll(ApiQueryClient.query(WikidataActionApiQuery.queryLanguages()));
} catch (IOException e) {
Logging.warn("Could not download language names! Only the language codes are displayed.", e);
}
synchronized (valueMap) {
if (qIdBeingDownloaded != null && qIdBeingDownloaded.equals(qId)) {
valueMap.clear();
valueMap.addAll(
newValues.entrySet().stream()
.map(it -> Pair.create(it.getValue(), it.getKey()))
newValues.values().stream()
.map(it -> Pair.create(it, languages.containsKey(it.getLangCode()) ? languages.get(it.getLangCode()) : it.getLangCode()))
.sorted(Comparator.comparing(it -> it.a.getLangCode()))
.collect(Collectors.toList())
);
parent.table.revalidate();
}
}
} catch (IOException e) {
new Notification(I18n.tr("Failed to download labels for {0}!", qId)).setIcon(WikipediaPlugin.W_IMAGE.get()).show();
}
parent.hideDownloadProgress();
parent.hideProgress();
}).start();
}
@Override
......@@ -106,17 +87,32 @@ class WikidataInfoLabelPanel extends JPanel {
@Override
public int getColumnCount() {
return 2;
return 3;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return columnIndex == 0 ? valueMap.get(rowIndex).a : valueMap.get(rowIndex).b;
switch (columnIndex) {
case 0: return valueMap.get(rowIndex).a.getLangCode();
case 1: return valueMap.get(rowIndex).b;
case 2:
default: return valueMap.get(rowIndex).a.getValue();
}
}
@Override
public String getColumnName(int column) {
return column == 0 ? "language" : "label";
switch (column) {
case 0: return I18n.tr("language code");
case 1: return I18n.tr("language");
case 2:
default: return I18n.tr("label");
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 3;
}
}
}
......@@ -5,10 +5,7 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.util.Collections;
import java.util.Map;
......@@ -20,7 +17,6 @@ import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import org.openstreetmap.josm.data.osm.DataSelectionListener;
import org.openstreetmap.josm.data.osm.DataSet;
......@@ -30,7 +26,6 @@ import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
import org.openstreetmap.josm.gui.MainApplication;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
import org.openstreetmap.josm.tools.GBC;
import org.openstreetmap.josm.tools.I18n;
import org.openstreetmap.josm.tools.OpenBrowser;
import org.wikipedia.WikipediaPlugin;
......@@ -38,6 +33,9 @@ import org.wikipedia.data.WikidataEntry;
import org.wikipedia.data.WikipediaEntry;
import org.wikipedia.tools.OsmPrimitiveUtil;
/**
* Toggle dialog that displays infos about the currently selected Wikidata item.
*/
public class WikidataInfoToggleDialog extends ToggleDialog {
private static final Logger L = Logger.getLogger(WikidataInfoToggleDialog.class.getName());
private static final String EMPTY_STRING = "";
......@@ -56,7 +54,7 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
private final JTabbedPane tabs = new JTabbedPane();
private final WikidataInfoLabelPanel labelTab = new WikidataInfoLabelPanel();
private final JPanel statementTab = new JPanel();
private final WikidataInfoClaimPanel statementTab = new WikidataInfoClaimPanel();
private final JPanel linkTab = new JPanel();
private final JButton webLinkButton = new JButton();
......@@ -98,25 +96,6 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
infoPanel.add(basicInfoPanel, BorderLayout.NORTH);
infoPanel.add(tabs, BorderLayout.CENTER);
// Set up statement tab
statementTab.setLayout(new GridBagLayout());
final GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.NORTH;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.insets = new Insets(1, 1, 1, 1);
constraints.fill = GridBagConstraints.BOTH;
// At the moment only dummy content
constraints.weightx = 1;
statementTab.add(new StatementPanel("instance of", "example", "dummy content"), constraints);
constraints.gridy++;
statementTab.add(new StatementPanel("start date", "42"), constraints);
constraints.gridy++;
statementTab.add(new StatementPanel("architect", "John Doe"), constraints);
constraints.gridy++;
constraints.weighty = 1;
statementTab.add(GBC.glue(0, 0), constraints);
linkTab.add(webLinkButton);
tabs.add(I18n.tr("Statements"), statementTab);
......@@ -126,7 +105,6 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
// Set up listeners
this.wikiDialog.list.addListSelectionListener(event -> updateDisplayedItem());
MainApplication.getLayerManager().addAndFireActiveLayerChangeListener(event -> {
System.out.println("Fire active layer change");
final DataSet previous = event.getPreviousDataSet();
final DataSet current = event.getSource().getActiveDataSet();
if (previous != null) {
......@@ -173,7 +151,9 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
}
} else if (wdTagsInDataset.size() >= 2) {
// More than one OSM object with valid wikidata=* tag is selected
final String itemList = wdTagsInDataset.entrySet().stream().map(it -> it.getKey() + " (" + it.getValue() + "×)").collect(Collectors.joining(", "));
final String itemList = wdTagsInDataset.entrySet().stream()
.map(it -> it.getKey() + " (" + it.getValue() + "×)")
.collect(Collectors.joining(", "));
displayMessage(itemList, I18n.tr("More than one OSM object is selected: {0}", itemList));
} else { // size == 1
// An OSM object or multiple OSM objects with exactly one valid wikidata=* tag (multiple tags with same value count as one)
......@@ -182,7 +162,7 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
}
}
private void displayItem(final String qId, final String label, final String description) {
private synchronized void displayItem(final String qId, final String label, final String description) {
if (qId != null && !qId.equals(getDisplayedItem())) {
mainPanel.removeAll();
setTitle(qId);
......@@ -190,28 +170,31 @@ public class WikidataInfoToggleDialog extends ToggleDialog {
descriptionLabel.setText(description);
setDisplayedItem(qId);
labelTab.clear();
labelTab.downloadLabelsFor(qId);
statementTab.downloadStatementsFor(qId);
webLinkButton.setAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
final String uri = "https://www.wikidata.org/wiki/" + qId;
final String error = OpenBrowser.displayUrl(uri);
if (error != null) {
new Notification(I18n.tr("Can't open website {0} in browser! Error message: {1}", uri, error)).setIcon(WikipediaPlugin.W_IMAGE.get()).show();
new Notification(I18n.tr("Can't open website {0} in browser! Error message: {1}", uri, error))
.setIcon(WikipediaPlugin.W_IMAGE.get())
.show();
}
}
});
webLinkButton.setText(I18n.tr("Open item {0} in browser", qId));
mainPanel.add(new JScrollPane(infoPanel));
mainPanel.add(infoPanel);
mainPanel.revalidate();
mainPanel.repaint();
}
}
private void displayMessage(final String title, final String message) {
private synchronized void displayMessage(final String title, final String message) {
mainPanel.removeAll();
setTitle(title);
setDisplayedItem(null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment