Revision 9e521c57
Added by Patrick Plitzner over 5 years ago
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/webimport/termimport/GfBioTerminologyImportComposite.java | ||
---|---|---|
8 | 8 |
*/ |
9 | 9 |
package eu.etaxonomy.taxeditor.view.webimport.termimport; |
10 | 10 |
|
11 |
import org.eclipse.jface.viewers.ComboViewer; |
|
12 | 11 |
import org.eclipse.jface.viewers.ListViewer; |
13 | 12 |
import org.eclipse.jface.viewers.TreeViewer; |
14 | 13 |
import org.eclipse.swt.SWT; |
15 | 14 |
import org.eclipse.swt.layout.GridData; |
16 | 15 |
import org.eclipse.swt.layout.GridLayout; |
17 | 16 |
import org.eclipse.swt.widgets.Button; |
18 |
import org.eclipse.swt.widgets.Combo; |
|
19 | 17 |
import org.eclipse.swt.widgets.Composite; |
20 | 18 |
import org.eclipse.swt.widgets.Label; |
21 | 19 |
import org.eclipse.swt.widgets.List; |
... | ... | |
39 | 37 |
private Text txtSearch; |
40 | 38 |
private Button btnSearch; |
41 | 39 |
private Composite composite; |
42 |
private Button btnRemoveTerminology; |
|
43 |
private ComboViewer comboTerminologies; |
|
44 | 40 |
private Composite composite_1; |
45 | 41 |
private Composite composite_2; |
46 | 42 |
private Label lblNewLabel; |
... | ... | |
60 | 56 |
private Label lblNewLabel_5; |
61 | 57 |
private Composite composite_5; |
62 | 58 |
private Label lblResultCount; |
59 |
private Label lblNewLabel_6; |
|
60 |
private Text textOntologies; |
|
61 |
private Button btnChooseOntology; |
|
63 | 62 |
|
64 | 63 |
public GfBioTerminologyImportComposite(Composite parent, int style) { |
65 | 64 |
super(parent, style); |
... | ... | |
67 | 66 |
|
68 | 67 |
composite = new Composite(this, SWT.NONE); |
69 | 68 |
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); |
70 |
composite.setLayout(new GridLayout(4, false));
|
|
69 |
composite.setLayout(new GridLayout(2, false));
|
|
71 | 70 |
|
72 | 71 |
txtSearch = new Text(composite, SWT.BORDER); |
73 | 72 |
txtSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); |
74 | 73 |
|
75 |
comboTerminologies = new ComboViewer(composite, SWT.NONE); |
|
76 |
Combo combo = comboTerminologies.getCombo(); |
|
77 |
combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); |
|
78 |
|
|
79 |
btnRemoveTerminology = new Button(composite, SWT.NONE); |
|
80 |
btnRemoveTerminology.setImage(ImageResources.getImage(ImageResources.TRASH_ICON)); |
|
81 |
|
|
82 | 74 |
btnSearch = new Button(composite, SWT.NONE); |
83 | 75 |
btnSearch.setText("Search"); |
84 | 76 |
|
85 | 77 |
composite_3 = new Composite(this, SWT.NONE); |
86 |
composite_3.setLayout(new GridLayout(3, false)); |
|
87 |
composite_3.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, false, 1, 1)); |
|
78 |
composite_3.setLayout(new GridLayout(6, false)); |
|
79 |
composite_3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1)); |
|
80 |
|
|
81 |
lblNewLabel_6 = new Label(composite_3, SWT.NONE); |
|
82 |
lblNewLabel_6.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
|
83 |
lblNewLabel_6.setText("Ontology"); |
|
84 |
|
|
85 |
textOntologies = new Text(composite_3, SWT.BORDER); |
|
86 |
textOntologies.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); |
|
87 |
|
|
88 |
btnChooseOntology = new Button(composite_3, SWT.NONE); |
|
89 |
btnChooseOntology.setImage(ImageResources.getImage(ImageResources.BROWSE_ICON)); |
|
88 | 90 |
|
89 | 91 |
lblNewLabel_4 = new Label(composite_3, SWT.NONE); |
90 | 92 |
lblNewLabel_4.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); |
... | ... | |
168 | 170 |
public Text getTxtSearch() { |
169 | 171 |
return txtSearch; |
170 | 172 |
} |
171 |
public Button getBtnRemoveTerminology() { |
|
172 |
return btnRemoveTerminology; |
|
173 |
} |
|
174 |
public ComboViewer getComboTerminologies() { |
|
175 |
return comboTerminologies; |
|
176 |
} |
|
177 | 173 |
public Text getLblDescription() { |
178 | 174 |
return txtDescription; |
179 | 175 |
} |
... | ... | |
195 | 191 |
public Label getLblResultCount() { |
196 | 192 |
return lblResultCount; |
197 | 193 |
} |
194 |
public Text getTextOntologies() { |
|
195 |
return textOntologies; |
|
196 |
} |
|
197 |
public Button getBtnChooseOntology() { |
|
198 |
return btnChooseOntology; |
|
199 |
} |
|
198 | 200 |
} |
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/webimport/termimport/GfBioTerminologyImportPresenter.java | ||
---|---|---|
11 | 11 |
import java.util.ArrayList; |
12 | 12 |
import java.util.Collection; |
13 | 13 |
import java.util.Iterator; |
14 |
import java.util.stream.Collectors; |
|
14 | 15 |
|
15 | 16 |
import org.eclipse.jface.util.LocalSelectionTransfer; |
16 |
import org.eclipse.jface.viewers.ArrayContentProvider; |
|
17 |
import org.eclipse.jface.viewers.ComboViewer; |
|
18 | 17 |
import org.eclipse.jface.viewers.ISelection; |
19 | 18 |
import org.eclipse.jface.viewers.IStructuredSelection; |
20 | 19 |
import org.eclipse.jface.viewers.StructuredSelection; |
20 |
import org.eclipse.jface.window.Window; |
|
21 | 21 |
import org.eclipse.swt.SWT; |
22 | 22 |
import org.eclipse.swt.dnd.DND; |
23 | 23 |
import org.eclipse.swt.dnd.DragSourceAdapter; |
... | ... | |
37 | 37 |
import eu.etaxonomy.taxeditor.preference.Resources; |
38 | 38 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.ParserUtil; |
39 | 39 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.TermParser; |
40 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.TerminologyParser; |
|
41 | 40 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestSearch; |
42 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestSuggest; |
|
43 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestTerminologies; |
|
44 | 41 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.OntologyTermWrapper; |
45 | 42 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.TerminologyWrapper; |
46 | 43 |
|
... | ... | |
51 | 48 |
*/ |
52 | 49 |
public class GfBioTerminologyImportPresenter { |
53 | 50 |
|
54 |
private static final String NO_CONNECTION_TITLE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_TITLE;
|
|
55 |
private static final String NO_CONNECTION_MESSAGE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_MESSAGE;
|
|
51 |
public static final String NO_CONNECTION_TITLE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_TITLE;
|
|
52 |
public static final String NO_CONNECTION_MESSAGE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_MESSAGE;
|
|
56 | 53 |
private static final String TXT_SEARCH_DEFAULT = Messages.GfBioTerminologyImportPresenter_TEXT_SEARCH_DEFAULT; |
57 | 54 |
|
58 | 55 |
private GfBioTerminologyImportComposite composite; |
56 |
private Collection<TerminologyWrapper> selectedOntologies = new ArrayList<>(); |
|
59 | 57 |
|
60 | 58 |
public GfBioTerminologyImportPresenter(GfBioTerminologyImportComposite composite) { |
61 | 59 |
super(); |
... | ... | |
99 | 97 |
} |
100 | 98 |
}); |
101 | 99 |
|
102 |
//terminology combo |
|
103 |
String response = new RequestTerminologies().request(); |
|
104 |
if(response==null){ |
|
105 |
MessagingUtils.informationDialog(NO_CONNECTION_TITLE, NO_CONNECTION_MESSAGE); |
|
106 |
return; |
|
107 |
} |
|
108 |
Collection<TerminologyWrapper> terminologies = TerminologyParser.parse(response); |
|
109 |
String comboDefaultText = Messages.GfBioTerminologyImportPresenter_COMBO_DEFAULT; |
|
110 |
ComboViewer comboOntologies = composite.getComboTerminologies(); |
|
111 |
comboOntologies.setLabelProvider(new TerminologyLabelProvider()); |
|
112 |
comboOntologies.setContentProvider(new ArrayContentProvider()); |
|
113 |
comboOntologies.setInput(terminologies); |
|
114 |
comboOntologies.getCombo().setText(comboDefaultText); |
|
115 |
|
|
116 |
composite.getBtnRemoveTerminology().addSelectionListener(new SelectionAdapter() { |
|
100 |
composite.getBtnChooseOntology().addSelectionListener(new SelectionAdapter() { |
|
117 | 101 |
@Override |
118 | 102 |
public void widgetSelected(SelectionEvent e) { |
119 |
composite.getComboTerminologies().setSelection(null); |
|
120 |
comboOntologies.getCombo().setText(comboDefaultText); |
|
103 |
OntologySelectionDialog dialog = new OntologySelectionDialog(composite.getShell(), selectedOntologies); |
|
104 |
if(dialog.open()==Window.OK){ |
|
105 |
selectedOntologies = dialog.getOntologies(); |
|
106 |
composite.getTextOntologies().setText(selectedOntologies.stream() |
|
107 |
.map(wrapper->wrapper.getAcronym()) |
|
108 |
.collect(Collectors.joining(", "))); |
|
109 |
} |
|
121 | 110 |
} |
122 | 111 |
}); |
123 | 112 |
|
... | ... | |
129 | 118 |
} |
130 | 119 |
}); |
131 | 120 |
|
132 |
composite.getBtnLoadDetails().addSelectionListener(new SelectionAdapter() { |
|
133 |
@Override |
|
134 |
public void widgetSelected(SelectionEvent e) { |
|
135 |
loadTermDetails(); |
|
136 |
} |
|
137 |
}); |
|
138 |
|
|
139 | 121 |
composite.getTreeTermHierarchy().setContentProvider(new OntologyTermContentProvider()); |
140 | 122 |
composite.getTreeTermHierarchy().setLabelProvider(new OntologyTermLabelProvider()); |
141 | 123 |
|
... | ... | |
211 | 193 |
} |
212 | 194 |
|
213 | 195 |
private void search(){ |
196 |
//clear result count |
|
197 |
composite.getLblResultCount().setText(""); |
|
198 |
|
|
214 | 199 |
String searchString = composite.getTxtSearch().getText(); |
215 | 200 |
if(searchString.equals(TXT_SEARCH_DEFAULT)){ |
216 | 201 |
return; |
217 | 202 |
} |
218 |
if(searchString.length()<4 && composite.getComboTerminologies().getSelection().isEmpty()){ |
|
219 |
MessagingUtils.informationDialog(Messages.GfBioTerminologyImportPresenter_SEARCH_TOO_SHORT_TITLE, Messages.GfBioTerminologyImportPresenter_SEARCH_TOO_SHORT_MESSAGE); |
|
203 |
String response = new RequestSearch(searchString, selectedOntologies).request(); |
|
204 |
if(response==null){ |
|
205 |
MessagingUtils.informationDialog(NO_CONNECTION_TITLE, NO_CONNECTION_MESSAGE); |
|
220 | 206 |
return; |
221 | 207 |
} |
222 |
String terminology = ""; //$NON-NLS-1$ |
|
223 |
ISelection selection = composite.getComboTerminologies().getSelection(); |
|
224 | 208 |
Collection<OntologyTermWrapper> wrapperList = new ArrayList<>(); |
225 |
if(selection instanceof IStructuredSelection && !selection.isEmpty()){ |
|
226 |
//TODO maybe add support for multiple terminology selection |
|
227 |
Object next = ((IStructuredSelection) selection).iterator().next(); |
|
228 |
if(next instanceof TerminologyWrapper){ |
|
229 |
terminology =((TerminologyWrapper) next).getAcronym(); |
|
230 |
} |
|
231 |
String response = new RequestSearch(searchString, terminology).request(); |
|
232 |
if(response==null){ |
|
233 |
MessagingUtils.informationDialog(NO_CONNECTION_TITLE, NO_CONNECTION_MESSAGE); |
|
234 |
return; |
|
235 |
} |
|
236 |
wrapperList = TermParser.parse(response); |
|
237 |
} |
|
238 |
else{ |
|
239 |
String response = new RequestSuggest(searchString).request(); |
|
240 |
if(response==null){ |
|
241 |
MessagingUtils.informationDialog(NO_CONNECTION_TITLE, NO_CONNECTION_MESSAGE); |
|
242 |
return; |
|
243 |
} |
|
244 |
wrapperList = TermParser.parse(response); |
|
245 |
} |
|
209 |
wrapperList = TermParser.parse(response); |
|
246 | 210 |
if(wrapperList.isEmpty()){ |
247 | 211 |
MessagingUtils.informationDialog(Messages.GfBioTerminologyImportPresenter_NO_RESULTS_TITLE, Messages.GfBioTerminologyImportPresenter_NO_RESULTS_MESSAGE); |
248 | 212 |
} |
249 | 213 |
composite.getTreeTermHierarchy().setInput(wrapperList); |
214 |
|
|
215 |
composite.getLblResultCount().setText(Integer.toString(wrapperList.size())); |
|
250 | 216 |
} |
251 | 217 |
|
252 | 218 |
} |
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/webimport/termimport/OntologySelectionDialog.java | ||
---|---|---|
1 |
/** |
|
2 |
* Copyright (C) 2018 EDIT |
|
3 |
* European Distributed Institute of Taxonomy |
|
4 |
* http://www.e-taxonomy.eu |
|
5 |
* |
|
6 |
* The contents of this file are subject to the Mozilla Public License Version 1.1 |
|
7 |
* See LICENSE.TXT at the top of this package for the full license terms. |
|
8 |
*/ |
|
9 |
package eu.etaxonomy.taxeditor.view.webimport.termimport; |
|
10 |
|
|
11 |
import java.util.ArrayList; |
|
12 |
import java.util.Arrays; |
|
13 |
import java.util.Collection; |
|
14 |
|
|
15 |
import org.eclipse.jface.dialogs.Dialog; |
|
16 |
import org.eclipse.jface.viewers.ArrayContentProvider; |
|
17 |
import org.eclipse.jface.viewers.CheckboxTableViewer; |
|
18 |
import org.eclipse.swt.SWT; |
|
19 |
import org.eclipse.swt.widgets.Composite; |
|
20 |
import org.eclipse.swt.widgets.Control; |
|
21 |
import org.eclipse.swt.widgets.Shell; |
|
22 |
import org.eclipse.swt.widgets.Table; |
|
23 |
|
|
24 |
import eu.etaxonomy.taxeditor.model.MessagingUtils; |
|
25 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.TerminologyParser; |
|
26 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestTerminologies; |
|
27 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.TerminologyWrapper; |
|
28 |
|
|
29 |
/** |
|
30 |
* Dialog to choose specimens for the character matrix.<br> |
|
31 |
* Filters specimens that have already been added. |
|
32 |
* @author pplitzner |
|
33 |
* @since Jan 3, 2018 |
|
34 |
* |
|
35 |
*/ |
|
36 |
public class OntologySelectionDialog extends Dialog { |
|
37 |
|
|
38 |
private CheckboxTableViewer list; |
|
39 |
|
|
40 |
private Collection<TerminologyWrapper> selectedOntologies = new ArrayList<>(); |
|
41 |
|
|
42 |
private Collection<TerminologyWrapper> initiallySelectedOntologies; |
|
43 |
|
|
44 |
|
|
45 |
protected OntologySelectionDialog(Shell parentShell, Collection<TerminologyWrapper> initiallySelectedOntologies) { |
|
46 |
super(parentShell); |
|
47 |
this.initiallySelectedOntologies = initiallySelectedOntologies; |
|
48 |
} |
|
49 |
|
|
50 |
@Override |
|
51 |
protected Control createDialogArea(Composite parent) { |
|
52 |
Table table = new Table(parent, SWT.CHECK | SWT.MULTI); |
|
53 |
list = new CheckboxTableViewer(table); |
|
54 |
String response = new RequestTerminologies().request(); |
|
55 |
if(response==null){ |
|
56 |
MessagingUtils.informationDialog(GfBioTerminologyImportPresenter.NO_CONNECTION_TITLE, |
|
57 |
GfBioTerminologyImportPresenter.NO_CONNECTION_MESSAGE); |
|
58 |
} |
|
59 |
else{ |
|
60 |
Collection<TerminologyWrapper> terminologies = TerminologyParser.parse(response); |
|
61 |
list.setLabelProvider(new TerminologyLabelProvider()); |
|
62 |
list.setContentProvider(new ArrayContentProvider()); |
|
63 |
list.setInput(terminologies); |
|
64 |
if(initiallySelectedOntologies!=null){ |
|
65 |
initiallySelectedOntologies.stream().forEach(wrapper->list.setChecked(wrapper, true)); |
|
66 |
} |
|
67 |
} |
|
68 |
return table; |
|
69 |
} |
|
70 |
|
|
71 |
@Override |
|
72 |
protected void configureShell(Shell newShell) { |
|
73 |
super.configureShell(newShell); |
|
74 |
newShell.setText("Choose ontologies"); |
|
75 |
} |
|
76 |
|
|
77 |
@Override |
|
78 |
protected void okPressed() { |
|
79 |
selectedOntologies.clear(); |
|
80 |
selectedOntologies = new ArrayList(Arrays.asList(list.getCheckedElements())); |
|
81 |
super.okPressed(); |
|
82 |
} |
|
83 |
|
|
84 |
@Override |
|
85 |
protected boolean isResizable() { |
|
86 |
return true; |
|
87 |
} |
|
88 |
|
|
89 |
public Collection<TerminologyWrapper> getOntologies(){ |
|
90 |
return selectedOntologies; |
|
91 |
} |
|
92 |
} |
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/webimport/termimport/requests/RequestSearch.java | ||
---|---|---|
9 | 9 |
package eu.etaxonomy.taxeditor.view.webimport.termimport.requests; |
10 | 10 |
|
11 | 11 |
import java.util.ArrayList; |
12 |
import java.util.Collection; |
|
12 | 13 |
import java.util.List; |
14 |
import java.util.stream.Collectors; |
|
15 |
|
|
16 |
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.TerminologyWrapper; |
|
13 | 17 |
|
14 | 18 |
/** |
15 | 19 |
* @author pplitzner |
... | ... | |
19 | 23 |
public class RequestSearch extends AbstractTerminologyServiceRequest{ |
20 | 24 |
|
21 | 25 |
private String searchString; |
22 |
private String terminology;
|
|
26 |
private Collection<TerminologyWrapper> selectedOntologies;
|
|
23 | 27 |
|
24 |
public RequestSearch(String searchString, String terminology) {
|
|
28 |
public RequestSearch(String searchString, Collection<TerminologyWrapper> selectedOntologies) {
|
|
25 | 29 |
super(); |
26 | 30 |
this.searchString = searchString; |
27 |
this.terminology = terminology;
|
|
31 |
this.selectedOntologies = selectedOntologies;
|
|
28 | 32 |
} |
29 | 33 |
|
30 | 34 |
@Override |
... | ... | |
40 | 44 |
@Override |
41 | 45 |
protected List<RequestParameter> getServiceParameters() { |
42 | 46 |
List<RequestParameter> params = new ArrayList<>(); |
43 |
params.add(new RequestParameter(TerminologyServiceConstants.ATTR_QUERY, ".*"+searchString+".*"));
|
|
47 |
params.add(new RequestParameter(TerminologyServiceConstants.ATTR_QUERY, searchString));
|
|
44 | 48 |
params.add(new RequestParameter("match_type", "regex")); |
45 | 49 |
params.add(new RequestParameter("internal_only", "true")); |
46 |
params.add(new RequestParameter(TerminologyServiceConstants.ATTR_TERMINOLOGIES, terminology)); |
|
50 |
params.add(new RequestParameter(TerminologyServiceConstants.ATTR_TERMINOLOGIES, |
|
51 |
selectedOntologies.stream() |
|
52 |
.map(wrapper->wrapper.getAcronym()) |
|
53 |
.collect(Collectors.joining(",")))); |
|
47 | 54 |
return params; |
48 | 55 |
} |
49 | 56 |
|
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/webimport/termimport/wrapper/TerminologyWrapper.java | ||
---|---|---|
38 | 38 |
return uri; |
39 | 39 |
} |
40 | 40 |
|
41 |
@Override |
|
42 |
public int hashCode() { |
|
43 |
final int prime = 31; |
|
44 |
int result = 1; |
|
45 |
result = prime * result + ((acronym == null) ? 0 : acronym.hashCode()); |
|
46 |
result = prime * result + ((description == null) ? 0 : description.hashCode()); |
|
47 |
result = prime * result + ((name == null) ? 0 : name.hashCode()); |
|
48 |
result = prime * result + ((uri == null) ? 0 : uri.hashCode()); |
|
49 |
return result; |
|
50 |
} |
|
51 |
|
|
52 |
@Override |
|
53 |
public boolean equals(Object obj) { |
|
54 |
if (this == obj) { |
|
55 |
return true; |
|
56 |
} |
|
57 |
if (obj == null) { |
|
58 |
return false; |
|
59 |
} |
|
60 |
if (getClass() != obj.getClass()) { |
|
61 |
return false; |
|
62 |
} |
|
63 |
TerminologyWrapper other = (TerminologyWrapper) obj; |
|
64 |
if (acronym == null) { |
|
65 |
if (other.acronym != null) { |
|
66 |
return false; |
|
67 |
} |
|
68 |
} else if (!acronym.equals(other.acronym)) { |
|
69 |
return false; |
|
70 |
} |
|
71 |
if (description == null) { |
|
72 |
if (other.description != null) { |
|
73 |
return false; |
|
74 |
} |
|
75 |
} else if (!description.equals(other.description)) { |
|
76 |
return false; |
|
77 |
} |
|
78 |
if (name == null) { |
|
79 |
if (other.name != null) { |
|
80 |
return false; |
|
81 |
} |
|
82 |
} else if (!name.equals(other.name)) { |
|
83 |
return false; |
|
84 |
} |
|
85 |
if (uri == null) { |
|
86 |
if (other.uri != null) { |
|
87 |
return false; |
|
88 |
} |
|
89 |
} else if (!uri.equals(other.uri)) { |
|
90 |
return false; |
|
91 |
} |
|
92 |
return true; |
|
93 |
} |
|
94 |
|
|
41 | 95 |
} |
Also available in: Unified diff
ref #7806 Implement selection dialog for ontologies