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

Last change on this file since 11534 was 11452, checked in by Don-vip, 7 years ago

sonar - fb-contrib:SEO_SUBOPTIMAL_EXPRESSION_ORDER - Performance - Method orders expressions in a conditional in a sub optimal way

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