source: josm/trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java@ 16673

Last change on this file since 16673 was 16673, checked in by simon04, 4 years ago

fix #19381 - Upload dialog: warn about large bounding box

  • Property svn:eol-style set to native
File size: 27.1 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6import static org.openstreetmap.josm.tools.I18n.trn;
7
8import java.awt.Component;
9import java.awt.Dimension;
10import java.awt.FlowLayout;
11import java.awt.GridBagLayout;
12import java.awt.event.ActionEvent;
13import java.awt.event.WindowAdapter;
14import java.awt.event.WindowEvent;
15import java.beans.PropertyChangeEvent;
16import java.beans.PropertyChangeListener;
17import java.lang.Character.UnicodeBlock;
18import java.util.ArrayList;
19import java.util.Collection;
20import java.util.Collections;
21import java.util.HashMap;
22import java.util.List;
23import java.util.Locale;
24import java.util.Map;
25import java.util.Map.Entry;
26import java.util.Optional;
27import java.util.stream.Collectors;
28
29import javax.swing.AbstractAction;
30import javax.swing.BorderFactory;
31import javax.swing.JButton;
32import javax.swing.JOptionPane;
33import javax.swing.JPanel;
34import javax.swing.JTabbedPane;
35
36import org.openstreetmap.josm.data.APIDataSet;
37import org.openstreetmap.josm.data.Version;
38import org.openstreetmap.josm.data.osm.Changeset;
39import org.openstreetmap.josm.data.osm.DataSet;
40import org.openstreetmap.josm.data.osm.OsmPrimitive;
41import org.openstreetmap.josm.gui.HelpAwareOptionPane;
42import org.openstreetmap.josm.gui.MainApplication;
43import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
44import org.openstreetmap.josm.gui.help.HelpUtil;
45import org.openstreetmap.josm.gui.util.GuiHelper;
46import org.openstreetmap.josm.gui.util.MultiLineFlowLayout;
47import org.openstreetmap.josm.gui.util.WindowGeometry;
48import org.openstreetmap.josm.io.OsmApi;
49import org.openstreetmap.josm.io.UploadStrategy;
50import org.openstreetmap.josm.io.UploadStrategySpecification;
51import org.openstreetmap.josm.spi.preferences.Config;
52import org.openstreetmap.josm.spi.preferences.PreferenceChangeEvent;
53import org.openstreetmap.josm.spi.preferences.PreferenceChangedListener;
54import org.openstreetmap.josm.spi.preferences.Setting;
55import org.openstreetmap.josm.tools.GBC;
56import org.openstreetmap.josm.tools.ImageProvider;
57import org.openstreetmap.josm.tools.InputMapUtils;
58import org.openstreetmap.josm.tools.Utils;
59
60/**
61 * This is a dialog for entering upload options like the parameters for
62 * the upload changeset and the strategy for opening/closing a changeset.
63 * @since 2025
64 */
65public class UploadDialog extends AbstractUploadDialog implements PropertyChangeListener, PreferenceChangedListener {
66 /** the unique instance of the upload dialog */
67 private static UploadDialog uploadDialog;
68
69 /** list of custom components that can be added by plugins at JOSM startup */
70 private static final Collection<Component> customComponents = new ArrayList<>();
71
72 /** the "created_by" changeset OSM key */
73 private static final String CREATED_BY = "created_by";
74
75 /** the panel with the objects to upload */
76 private UploadedObjectsSummaryPanel pnlUploadedObjects;
77 /** the panel to select the changeset used */
78 private ChangesetManagementPanel pnlChangesetManagement;
79
80 private BasicUploadSettingsPanel pnlBasicUploadSettings;
81
82 private UploadStrategySelectionPanel pnlUploadStrategySelectionPanel;
83
84 /** checkbox for selecting whether an atomic upload is to be used */
85 private TagSettingsPanel pnlTagSettings;
86 /** the tabbed pane used below of the list of primitives */
87 private JTabbedPane tpConfigPanels;
88 /** the upload button */
89 private JButton btnUpload;
90
91 /** the changeset comment model keeping the state of the changeset comment */
92 private final transient ChangesetCommentModel changesetCommentModel = new ChangesetCommentModel();
93 private final transient ChangesetCommentModel changesetSourceModel = new ChangesetCommentModel();
94 private final transient ChangesetReviewModel changesetReviewModel = new ChangesetReviewModel();
95
96 private transient DataSet dataSet;
97
98 /**
99 * Constructs a new {@code UploadDialog}.
100 */
101 public UploadDialog() {
102 super(GuiHelper.getFrameForComponent(MainApplication.getMainFrame()), ModalityType.DOCUMENT_MODAL);
103 build();
104 pack();
105 }
106
107 /**
108 * Replies the unique instance of the upload dialog
109 *
110 * @return the unique instance of the upload dialog
111 */
112 public static synchronized UploadDialog getUploadDialog() {
113 if (uploadDialog == null) {
114 uploadDialog = new UploadDialog();
115 }
116 return uploadDialog;
117 }
118
119 /**
120 * builds the content panel for the upload dialog
121 *
122 * @return the content panel
123 */
124 protected JPanel buildContentPanel() {
125 JPanel pnl = new JPanel(new GridBagLayout());
126 pnl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
127
128 // the panel with the list of uploaded objects
129 pnlUploadedObjects = new UploadedObjectsSummaryPanel();
130 pnl.add(pnlUploadedObjects, GBC.eol().fill(GBC.BOTH));
131
132 // Custom components
133 for (Component c : customComponents) {
134 pnl.add(c, GBC.eol().fill(GBC.HORIZONTAL));
135 }
136
137 // a tabbed pane with configuration panels in the lower half
138 tpConfigPanels = new CompactTabbedPane();
139
140 pnlBasicUploadSettings = new BasicUploadSettingsPanel(changesetCommentModel, changesetSourceModel, changesetReviewModel);
141 tpConfigPanels.add(pnlBasicUploadSettings);
142 tpConfigPanels.setTitleAt(0, tr("Settings"));
143 tpConfigPanels.setToolTipTextAt(0, tr("Decide how to upload the data and which changeset to use"));
144
145 pnlTagSettings = new TagSettingsPanel(changesetCommentModel, changesetSourceModel, changesetReviewModel);
146 tpConfigPanels.add(pnlTagSettings);
147 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
148 tpConfigPanels.setToolTipTextAt(1, tr("Apply tags to the changeset data is uploaded to"));
149
150 pnlChangesetManagement = new ChangesetManagementPanel(changesetCommentModel);
151 tpConfigPanels.add(pnlChangesetManagement);
152 tpConfigPanels.setTitleAt(2, tr("Changesets"));
153 tpConfigPanels.setToolTipTextAt(2, tr("Manage open changesets and select a changeset to upload to"));
154
155 pnlUploadStrategySelectionPanel = new UploadStrategySelectionPanel();
156 tpConfigPanels.add(pnlUploadStrategySelectionPanel);
157 tpConfigPanels.setTitleAt(3, tr("Advanced"));
158 tpConfigPanels.setToolTipTextAt(3, tr("Configure advanced settings"));
159
160 pnl.add(tpConfigPanels, GBC.eol().fill(GBC.HORIZONTAL));
161
162 pnl.add(buildActionPanel(), GBC.eol().fill(GBC.HORIZONTAL));
163 return pnl;
164 }
165
166 /**
167 * builds the panel with the OK and CANCEL buttons
168 *
169 * @return The panel with the OK and CANCEL buttons
170 */
171 protected JPanel buildActionPanel() {
172 JPanel pnl = new JPanel(new MultiLineFlowLayout(FlowLayout.CENTER));
173 pnl.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
174
175 // -- upload button
176 btnUpload = new JButton(new UploadAction(this));
177 pnl.add(btnUpload);
178 btnUpload.setFocusable(true);
179 InputMapUtils.enableEnter(btnUpload);
180 InputMapUtils.addCtrlEnterAction(getRootPane(), btnUpload.getAction());
181
182 // -- cancel button
183 CancelAction cancelAction = new CancelAction(this);
184 pnl.add(new JButton(cancelAction));
185 InputMapUtils.addEscapeAction(getRootPane(), cancelAction);
186 pnl.add(new JButton(new ContextSensitiveHelpAction(ht("/Dialog/Upload"))));
187 HelpUtil.setHelpContext(getRootPane(), ht("/Dialog/Upload"));
188 return pnl;
189 }
190
191 /**
192 * builds the gui
193 */
194 protected void build() {
195 setTitle(tr("Upload to ''{0}''", OsmApi.getOsmApi().getBaseUrl()));
196 setContentPane(buildContentPanel());
197
198 addWindowListener(new WindowEventHandler());
199
200 // make sure the configuration panels listen to each other changes
201 //
202 pnlChangesetManagement.addPropertyChangeListener(this);
203 pnlChangesetManagement.addPropertyChangeListener(
204 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
205 );
206 pnlChangesetManagement.addPropertyChangeListener(this);
207 pnlUploadedObjects.addPropertyChangeListener(
208 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
209 );
210 pnlUploadedObjects.addPropertyChangeListener(pnlUploadStrategySelectionPanel);
211 pnlUploadStrategySelectionPanel.addPropertyChangeListener(
212 pnlBasicUploadSettings.getUploadParameterSummaryPanel()
213 );
214
215 // users can click on either of two links in the upload parameter
216 // summary handler. This installs the handler for these two events.
217 // We simply select the appropriate tab in the tabbed pane with the configuration dialogs.
218 //
219 pnlBasicUploadSettings.getUploadParameterSummaryPanel().setConfigurationParameterRequestListener(
220 new ConfigurationParameterRequestHandler() {
221 @Override
222 public void handleUploadStrategyConfigurationRequest() {
223 tpConfigPanels.setSelectedIndex(3);
224 }
225
226 @Override
227 public void handleChangesetConfigurationRequest() {
228 tpConfigPanels.setSelectedIndex(2);
229 }
230 }
231 );
232
233 pnlBasicUploadSettings.setUploadTagDownFocusTraversalHandlers(e -> btnUpload.requestFocusInWindow());
234
235 setMinimumSize(new Dimension(600, 350));
236
237 Config.getPref().addPreferenceChangeListener(this);
238 }
239
240 /**
241 * Sets the collection of primitives to upload
242 *
243 * @param toUpload the dataset with the objects to upload. If null, assumes the empty
244 * set of objects to upload
245 *
246 */
247 public void setUploadedPrimitives(APIDataSet toUpload) {
248 if (toUpload == null) {
249 if (pnlUploadedObjects != null) {
250 List<OsmPrimitive> emptyList = Collections.emptyList();
251 pnlUploadedObjects.setUploadedPrimitives(emptyList, emptyList, emptyList);
252 }
253 return;
254 }
255 pnlBasicUploadSettings.setUploadedPrimitives(toUpload.getPrimitives());
256 pnlUploadedObjects.setUploadedPrimitives(
257 toUpload.getPrimitivesToAdd(),
258 toUpload.getPrimitivesToUpdate(),
259 toUpload.getPrimitivesToDelete()
260 );
261 }
262
263 /**
264 * Sets the tags for this upload based on (later items overwrite earlier ones):
265 * <ul>
266 * <li>previous "source" and "comment" input</li>
267 * <li>the tags set in the dataset (see {@link DataSet#getChangeSetTags()})</li>
268 * <li>the tags from the selected open changeset</li>
269 * <li>the JOSM user agent (see {@link Version#getAgentString(boolean)})</li>
270 * </ul>
271 *
272 * @param dataSet to obtain the tags set in the dataset
273 */
274 public void setChangesetTags(DataSet dataSet) {
275 setChangesetTags(dataSet, false);
276 }
277
278 /**
279 * Sets the tags for this upload based on (later items overwrite earlier ones):
280 * <ul>
281 * <li>previous "source" and "comment" input</li>
282 * <li>the tags set in the dataset (see {@link DataSet#getChangeSetTags()})</li>
283 * <li>the tags from the selected open changeset</li>
284 * <li>the JOSM user agent (see {@link Version#getAgentString(boolean)})</li>
285 * </ul>
286 *
287 * @param dataSet to obtain the tags set in the dataset
288 * @param keepSourceComment if {@code true}, keep upload {@code source} and {@code comment} current values from models
289 */
290 private void setChangesetTags(DataSet dataSet, boolean keepSourceComment) {
291 final Map<String, String> tags = new HashMap<>();
292
293 // obtain from previous input
294 if (!keepSourceComment) {
295 tags.put("source", getLastChangesetSourceFromHistory());
296 tags.put("comment", getLastChangesetCommentFromHistory());
297 }
298
299 // obtain from dataset
300 if (dataSet != null) {
301 tags.putAll(dataSet.getChangeSetTags());
302 }
303 this.dataSet = dataSet;
304
305 // obtain from selected open changeset
306 if (pnlChangesetManagement.getSelectedChangeset() != null) {
307 tags.putAll(pnlChangesetManagement.getSelectedChangeset().getKeys());
308 }
309
310 // set/adapt created_by
311 final String agent = Version.getInstance().getAgentString(false);
312 final String createdBy = tags.get(CREATED_BY);
313 if (createdBy == null || createdBy.isEmpty()) {
314 tags.put(CREATED_BY, agent);
315 } else if (!createdBy.contains(agent)) {
316 tags.put(CREATED_BY, createdBy + ';' + agent);
317 }
318
319 // remove empty values
320 tags.keySet().removeIf(key -> {
321 final String v = tags.get(key);
322 return v == null || v.isEmpty();
323 });
324
325 // ignore source/comment to keep current values from models ?
326 if (keepSourceComment) {
327 tags.put("source", changesetSourceModel.getComment());
328 tags.put("comment", changesetCommentModel.getComment());
329 }
330
331 pnlTagSettings.initFromTags(tags);
332 pnlTagSettings.tableChanged(null);
333 pnlBasicUploadSettings.discardAllUndoableEdits();
334 }
335
336 @Override
337 public void rememberUserInput() {
338 pnlBasicUploadSettings.rememberUserInput();
339 pnlUploadStrategySelectionPanel.rememberUserInput();
340 }
341
342 /**
343 * Initializes the panel for user input
344 */
345 public void startUserInput() {
346 tpConfigPanels.setSelectedIndex(0);
347 pnlBasicUploadSettings.startUserInput();
348 pnlTagSettings.startUserInput();
349 pnlUploadStrategySelectionPanel.initFromPreferences();
350 UploadParameterSummaryPanel pnl = pnlBasicUploadSettings.getUploadParameterSummaryPanel();
351 pnl.setUploadStrategySpecification(pnlUploadStrategySelectionPanel.getUploadStrategySpecification());
352 pnl.setCloseChangesetAfterNextUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
353 pnl.setNumObjects(pnlUploadedObjects.getNumObjectsToUpload());
354 }
355
356 /**
357 * Replies the current changeset
358 *
359 * @return the current changeset
360 */
361 public Changeset getChangeset() {
362 Changeset cs = Optional.ofNullable(pnlChangesetManagement.getSelectedChangeset()).orElseGet(Changeset::new);
363 cs.setKeys(pnlTagSettings.getTags(false));
364 return cs;
365 }
366
367 /**
368 * Sets the changeset to be used in the next upload
369 *
370 * @param cs the changeset
371 */
372 public void setSelectedChangesetForNextUpload(Changeset cs) {
373 pnlChangesetManagement.setSelectedChangesetForNextUpload(cs);
374 }
375
376 @Override
377 public UploadStrategySpecification getUploadStrategySpecification() {
378 UploadStrategySpecification spec = pnlUploadStrategySelectionPanel.getUploadStrategySpecification();
379 spec.setCloseChangesetAfterUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
380 return spec;
381 }
382
383 @Override
384 public String getUploadComment() {
385 return changesetCommentModel.getComment();
386 }
387
388 @Override
389 public String getUploadSource() {
390 return changesetSourceModel.getComment();
391 }
392
393 @Override
394 public void setVisible(boolean visible) {
395 if (visible) {
396 new WindowGeometry(
397 getClass().getName() + ".geometry",
398 WindowGeometry.centerInWindow(
399 MainApplication.getMainFrame(),
400 new Dimension(400, 600)
401 )
402 ).applySafe(this);
403 startUserInput();
404 } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
405 new WindowGeometry(this).remember(getClass().getName() + ".geometry");
406 }
407 super.setVisible(visible);
408 }
409
410 /**
411 * Adds a custom component to this dialog.
412 * Custom components added at JOSM startup are displayed between the objects list and the properties tab pane.
413 * @param c The custom component to add. If {@code null}, this method does nothing.
414 * @return {@code true} if the collection of custom components changed as a result of the call
415 * @since 5842
416 */
417 public static boolean addCustomComponent(Component c) {
418 if (c != null) {
419 return customComponents.add(c);
420 }
421 return false;
422 }
423
424 static final class CompactTabbedPane extends JTabbedPane {
425 @Override
426 public Dimension getPreferredSize() {
427 // This probably fixes #18523. Don't know why. Don't know how. It just does.
428 super.getPreferredSize();
429 // make sure the tabbed pane never grabs more space than necessary
430 return super.getMinimumSize();
431 }
432 }
433
434 /**
435 * Handles an upload.
436 */
437 static class UploadAction extends AbstractAction {
438
439 private final transient IUploadDialog dialog;
440
441 UploadAction(IUploadDialog dialog) {
442 this.dialog = dialog;
443 putValue(NAME, tr("Upload Changes"));
444 new ImageProvider("upload").getResource().attachImageIcon(this, true);
445 putValue(SHORT_DESCRIPTION, tr("Upload the changed primitives"));
446 }
447
448 protected void warnIllegalChunkSize() {
449 HelpAwareOptionPane.showOptionDialog(
450 (Component) dialog,
451 tr("Please enter a valid chunk size first"),
452 tr("Illegal chunk size"),
453 JOptionPane.ERROR_MESSAGE,
454 ht("/Dialog/Upload#IllegalChunkSize")
455 );
456 }
457
458 static boolean isUploadCommentTooShort(String comment) {
459 String s = Utils.strip(comment);
460 boolean result = true;
461 if (!s.isEmpty()) {
462 UnicodeBlock block = Character.UnicodeBlock.of(s.charAt(0));
463 if (block != null && block.toString().contains("CJK")) {
464 result = s.length() < 4;
465 } else {
466 result = s.length() < 10;
467 }
468 }
469 return result;
470 }
471
472 private static String lower(String s) {
473 return s.toLowerCase(Locale.ENGLISH);
474 }
475
476 static String validateUploadTag(String uploadValue, String preferencePrefix,
477 List<String> defMandatory, List<String> defForbidden, List<String> defException) {
478 String uploadValueLc = lower(uploadValue);
479 // Check mandatory terms
480 List<String> missingTerms = Config.getPref().getList(preferencePrefix+".mandatory-terms", defMandatory)
481 .stream().map(UploadAction::lower).filter(x -> !uploadValueLc.contains(x)).collect(Collectors.toList());
482 if (!missingTerms.isEmpty()) {
483 return tr("The following required terms are missing: {0}", missingTerms);
484 }
485 // Check forbidden terms
486 List<String> exceptions = Config.getPref().getList(preferencePrefix+".exception-terms", defException);
487 List<String> forbiddenTerms = Config.getPref().getList(preferencePrefix+".forbidden-terms", defForbidden)
488 .stream().map(UploadAction::lower)
489 .filter(x -> uploadValueLc.contains(x) && exceptions.stream().noneMatch(uploadValueLc::contains))
490 .collect(Collectors.toList());
491 if (!forbiddenTerms.isEmpty()) {
492 return tr("The following forbidden terms have been found: {0}", forbiddenTerms);
493 }
494 return null;
495 }
496
497 @Override
498 public void actionPerformed(ActionEvent e) {
499 // force update of model in case dialog is closed before focus lost event, see #17452
500 dialog.forceUpdateActiveField();
501
502 /* test for empty tags in the changeset metadata and proceed only after user's confirmation.
503 * though, accept if key and value are empty (cf. xor). */
504 List<String> emptyChangesetTags = new ArrayList<>();
505 for (final Entry<String, String> i : dialog.getTags(true).entrySet()) {
506 final boolean isKeyEmpty = Utils.isStripEmpty(i.getKey());
507 final boolean isValueEmpty = Utils.isStripEmpty(i.getValue());
508 final boolean ignoreKey = "comment".equals(i.getKey()) || "source".equals(i.getKey());
509 if ((isKeyEmpty ^ isValueEmpty) && !ignoreKey) {
510 emptyChangesetTags.add(tr("{0}={1}", i.getKey(), i.getValue()));
511 }
512 }
513 if (!emptyChangesetTags.isEmpty() && JOptionPane.OK_OPTION != JOptionPane.showConfirmDialog(
514 MainApplication.getMainFrame(),
515 trn(
516 "<html>The following changeset tag contains an empty key/value:<br>{0}<br>Continue?</html>",
517 "<html>The following changeset tags contain an empty key/value:<br>{0}<br>Continue?</html>",
518 emptyChangesetTags.size(), Utils.joinAsHtmlUnorderedList(emptyChangesetTags)),
519 tr("Empty metadata"),
520 JOptionPane.OK_CANCEL_OPTION,
521 JOptionPane.WARNING_MESSAGE
522 )) {
523 dialog.handleMissingComment();
524 return;
525 }
526
527 UploadStrategySpecification strategy = dialog.getUploadStrategySpecification();
528 if (strategy.getStrategy() == UploadStrategy.CHUNKED_DATASET_STRATEGY
529 && strategy.getChunkSize() == UploadStrategySpecification.UNSPECIFIED_CHUNK_SIZE) {
530 warnIllegalChunkSize();
531 dialog.handleIllegalChunkSize();
532 return;
533 }
534 if (dialog instanceof AbstractUploadDialog) {
535 ((AbstractUploadDialog) dialog).setCanceled(false);
536 ((AbstractUploadDialog) dialog).setVisible(false);
537 }
538 }
539 }
540
541 /**
542 * Action for canceling the dialog.
543 */
544 static class CancelAction extends AbstractAction {
545
546 private final transient IUploadDialog dialog;
547
548 CancelAction(IUploadDialog dialog) {
549 this.dialog = dialog;
550 putValue(NAME, tr("Cancel"));
551 new ImageProvider("cancel").getResource().attachImageIcon(this, true);
552 putValue(SHORT_DESCRIPTION, tr("Cancel the upload and resume editing"));
553 }
554
555 @Override
556 public void actionPerformed(ActionEvent e) {
557 if (dialog instanceof AbstractUploadDialog) {
558 ((AbstractUploadDialog) dialog).setCanceled(true);
559 ((AbstractUploadDialog) dialog).setVisible(false);
560 }
561 }
562 }
563
564 /**
565 * Listens to window closing events and processes them as cancel events.
566 * Listens to window open events and initializes user input
567 */
568 class WindowEventHandler extends WindowAdapter {
569 private boolean activatedOnce;
570
571 @Override
572 public void windowClosing(WindowEvent e) {
573 setCanceled(true);
574 }
575
576 @Override
577 public void windowActivated(WindowEvent e) {
578 if (!activatedOnce && tpConfigPanels.getSelectedIndex() == 0) {
579 pnlBasicUploadSettings.initEditingOfUploadComment();
580 activatedOnce = true;
581 }
582 }
583 }
584
585 /* -------------------------------------------------------------------------- */
586 /* Interface PropertyChangeListener */
587 /* -------------------------------------------------------------------------- */
588 @Override
589 public void propertyChange(PropertyChangeEvent evt) {
590 if (evt.getPropertyName().equals(ChangesetManagementPanel.SELECTED_CHANGESET_PROP)) {
591 Changeset cs = (Changeset) evt.getNewValue();
592 setChangesetTags(dataSet, cs == null); // keep comment/source of first tab for new changesets
593 if (cs == null) {
594 tpConfigPanels.setTitleAt(1, tr("Tags of new changeset"));
595 } else {
596 tpConfigPanels.setTitleAt(1, tr("Tags of changeset {0}", cs.getId()));
597 }
598 }
599 }
600
601 /* -------------------------------------------------------------------------- */
602 /* Interface PreferenceChangedListener */
603 /* -------------------------------------------------------------------------- */
604 @Override
605 public void preferenceChanged(PreferenceChangeEvent e) {
606 if (e.getKey() != null
607 && e.getSource() != getClass()
608 && e.getSource() != BasicUploadSettingsPanel.class) {
609 switch (e.getKey()) {
610 case "osm-server.url":
611 osmServerUrlChanged(e.getNewValue());
612 break;
613 case BasicUploadSettingsPanel.HISTORY_KEY:
614 case BasicUploadSettingsPanel.SOURCE_HISTORY_KEY:
615 pnlBasicUploadSettings.refreshHistoryComboBoxes();
616 break;
617 default:
618 return;
619 }
620 }
621 }
622
623 private void osmServerUrlChanged(Setting<?> newValue) {
624 final String url;
625 if (newValue == null || newValue.getValue() == null) {
626 url = OsmApi.getOsmApi().getBaseUrl();
627 } else {
628 url = newValue.getValue().toString();
629 }
630 setTitle(tr("Upload to ''{0}''", url));
631 }
632
633 private static String getLastChangesetTagFromHistory(String historyKey, List<String> def) {
634 Collection<String> history = Config.getPref().getList(historyKey, def);
635 long age = System.currentTimeMillis() / 1000 - BasicUploadSettingsPanel.getHistoryLastUsedKey();
636 if (age < BasicUploadSettingsPanel.getHistoryMaxAgeKey() && !history.isEmpty()) {
637 return history.iterator().next();
638 }
639 return null;
640 }
641
642 /**
643 * Returns the last changeset comment from history.
644 * @return the last changeset comment from history
645 */
646 public static String getLastChangesetCommentFromHistory() {
647 return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.HISTORY_KEY, new ArrayList<String>());
648 }
649
650 /**
651 * Returns the last changeset source from history.
652 * @return the last changeset source from history
653 */
654 public static String getLastChangesetSourceFromHistory() {
655 return getLastChangesetTagFromHistory(BasicUploadSettingsPanel.SOURCE_HISTORY_KEY, BasicUploadSettingsPanel.getDefaultSources());
656 }
657
658 @Override
659 public Map<String, String> getTags(boolean keepEmpty) {
660 return pnlTagSettings.getTags(keepEmpty);
661 }
662
663 @Override
664 public void handleMissingComment() {
665 tpConfigPanels.setSelectedIndex(0);
666 pnlBasicUploadSettings.initEditingOfUploadComment();
667 }
668
669 @Override
670 public void handleMissingSource() {
671 tpConfigPanels.setSelectedIndex(0);
672 pnlBasicUploadSettings.initEditingOfUploadSource();
673 }
674
675 @Override
676 public void handleIllegalChunkSize() {
677 tpConfigPanels.setSelectedIndex(0);
678 }
679
680 @Override
681 public void forceUpdateActiveField() {
682 if (tpConfigPanels.getSelectedComponent() == pnlBasicUploadSettings) {
683 pnlBasicUploadSettings.forceUpdateActiveField();
684 }
685 }
686
687 /**
688 * Clean dialog state and release resources.
689 * @since 14251
690 */
691 public void clean() {
692 setUploadedPrimitives(null);
693 dataSet = null;
694 }
695}
Note: See TracBrowser for help on using the repository browser.