- Timestamp:
- 2009-10-26T16:51:21+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java
r2323 r2325 10 10 import java.util.ArrayList; 11 11 import java.util.List; 12 import java.util.concurrent.Future; 12 13 14 import org.openstreetmap.josm.Main; 13 15 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTaskList; 14 16 import org.openstreetmap.josm.data.osm.DataSource; … … 81 83 // bounds defined? => use the bbox downloader 82 84 // 83 new DownloadOsmTaskList().download(false, areas, new PleaseWaitProgressMonitor(tr("Updating data"))); 85 final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(tr("Download data")); 86 final Future<?> future = new DownloadOsmTaskList().download(false /* no new layer */, areas, monitor); 87 Main.worker.submit( 88 new Runnable() { 89 public void run() { 90 try { 91 future.get(); 92 } catch(Exception e) { 93 e.printStackTrace(); 94 return; 95 } 96 monitor.close(); 97 } 98 } 99 ); 84 100 } 85 101 } -
trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTaskList.java
r2322 r2325 3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 5 6 6 7 import java.awt.EventQueue; 7 import java.awt.event.ActionEvent;8 import java.awt.event.ActionListener;9 8 import java.awt.geom.Area; 10 9 import java.awt.geom.Rectangle2D; … … 24 23 import org.openstreetmap.josm.data.osm.DataSet; 25 24 import org.openstreetmap.josm.data.osm.OsmPrimitive; 25 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 26 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; 26 27 import org.openstreetmap.josm.gui.layer.Layer; 27 28 import org.openstreetmap.josm.gui.layer.OsmDataLayer; … … 29 30 import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener; 30 31 import org.openstreetmap.josm.tools.ExceptionUtil; 32 import org.openstreetmap.josm.tools.ImageProvider; 31 33 32 34 /** 33 35 * This class encapsulates the downloading of several bounding boxes that would otherwise be too 34 * large to download in one go. Error messages will be collected for all downloads and displayed 35 * a s alist in the end.36 * large to download in one go. Error messages will be collected for all downloads and displayed as 37 * a list in the end. 36 38 * @author xeen 37 * 39 * 38 40 */ 39 public class DownloadOsmTaskList implements Runnable{41 public class DownloadOsmTaskList { 40 42 private List<DownloadTask> osmTasks = new LinkedList<DownloadTask>(); 41 43 private List<Future<?>> osmTaskFutures = new LinkedList<Future<?>>(); … … 49 51 public Future<?> download(boolean newLayer, List<Rectangle2D> rects, ProgressMonitor progressMonitor) { 50 52 this.progressMonitor = progressMonitor; 51 if (newLayer) {53 if (newLayer) { 52 54 Layer l = new OsmDataLayer(new DataSet(), OsmDataLayer.createNewName(), null); 53 55 Main.main.addLayer(l); … … 57 59 progressMonitor.beginTask(null, rects.size()); 58 60 int i = 0; 59 for (Rectangle2D td : rects) {61 for (Rectangle2D td : rects) { 60 62 i++; 61 63 DownloadTask dt = new DownloadOsmTask(); 62 64 ProgressMonitor childProgress = progressMonitor.createSubTaskMonitor(1, false); 63 65 childProgress.setSilent(true); 64 childProgress.setCustomText(tr("Download {0} of {1} ({2} left)", i, rects.size(), rects.size() -i));66 childProgress.setCustomText(tr("Download {0} of {1} ({2} left)", i, rects.size(), rects.size() - i)); 65 67 Future<?> future = dt.download(null, td.getMinY(), td.getMinX(), td.getMaxY(), td.getMaxX(), childProgress); 66 68 osmTaskFutures.add(future); 67 69 osmTasks.add(dt); 68 70 } 69 progressMonitor.addCancelListener( 70 new CancelListener() { 71 public void operationCanceled() { 72 for (DownloadTask dt: osmTasks) { 73 dt.cancel(); 74 } 75 } 76 } 77 ); 78 return Main.worker.submit(this); 71 progressMonitor.addCancelListener(new CancelListener() { 72 public void operationCanceled() { 73 for (DownloadTask dt : osmTasks) { 74 dt.cancel(); 75 } 76 } 77 }); 78 return Main.worker.submit(new PostDownloadProcessor()); 79 79 } 80 80 … … 84 84 * @param The Collection of Areas to download 85 85 */ 86 public voiddownload(boolean newLayer, Collection<Area> areas, ProgressMonitor progressMonitor) {86 public Future<?> download(boolean newLayer, Collection<Area> areas, ProgressMonitor progressMonitor) { 87 87 progressMonitor.beginTask(tr("Updating data")); 88 88 try { 89 89 List<Rectangle2D> rects = new LinkedList<Rectangle2D>(); 90 for (Area a : areas) {90 for (Area a : areas) { 91 91 rects.add(a.getBounds2D()); 92 92 } 93 93 94 download(newLayer, rects, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));94 return download(newLayer, rects, progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false)); 95 95 } finally { 96 96 progressMonitor.finishTask(); … … 99 99 100 100 /** 101 * Grabs and displays the error messages after all download threads have finished. 102 */ 103 public void run() { 104 progressMonitor.finishTask(); 105 106 // wait for all tasks to finish 107 // 108 for (Future<?> future: osmTaskFutures) { 109 try { 110 future.get(); 111 } catch(Exception e) { 112 e.printStackTrace(); 113 return; 114 } 115 } 116 LinkedHashSet<Object> errors = new LinkedHashSet<Object>(); 117 for(DownloadTask dt : osmTasks) { 118 errors.addAll(dt.getErrorObjects()); 119 } 120 if (!errors.isEmpty()) { 121 StringBuffer sb = new StringBuffer(); 122 for (Object error:errors) { 123 if (error instanceof String) { 124 sb.append("<li>").append(error).append("</li>").append("<br>"); 125 } else if (error instanceof Exception) { 126 sb.append("<li>").append(ExceptionUtil.explainException((Exception)error)).append("</li>").append("<br>"); 127 } 128 } 129 sb.insert(0, "<ul>"); 130 sb.append("</ul>"); 131 132 JOptionPane.showMessageDialog( 133 Main.parent, 134 "<html>"+tr("The following errors occurred during mass download: {0}", sb.toString()) 135 +"</html>", 136 tr("Errors during Download"), 137 JOptionPane.ERROR_MESSAGE); 138 return; 139 } 140 141 // FIXME: this is a hack. We assume that the user canceled the whole download if at least 142 // one task was canceled or if it failed 143 // 144 for (DownloadTask task: osmTasks) { 145 if (task instanceof DownloadOsmTask) { 146 DownloadOsmTask osmTask = (DownloadOsmTask)task; 147 if (osmTask.isCanceled() || osmTask.isFailed()) 148 return; 149 } 150 } 151 final OsmDataLayer editLayer = Main.map.mapView.getEditLayer(); 152 if (editLayer != null) { 153 Set<OsmPrimitive> myPrimitives = getCompletePrimitives(editLayer.data); 154 for (DownloadTask task : osmTasks) { 155 if(task instanceof DownloadOsmTask) { 156 DataSet ds = ((DownloadOsmTask)task).getDownloadedData(); 157 if (ds != null) { 158 myPrimitives.removeAll(ds.nodes); 159 myPrimitives.removeAll(ds.ways); 160 myPrimitives.removeAll(ds.relations); 161 } 162 } 163 } 164 if (! myPrimitives.isEmpty()) { 165 handlePotentiallyDeletedPrimitives(myPrimitives); 166 } 167 } 168 } 169 170 171 /** 172 * Replies the set of ids of all complete primitives (i.e. those with 173 * ! primitive.incomplete) 174 * 175 * @return the set of ids of all complete primitives 101 * Replies the set of ids of all complete, non-new primitives (i.e. those with ! 102 * primitive.incomplete) 103 * 104 * @return the set of ids of all complete, non-new primitives 176 105 */ 177 106 protected Set<OsmPrimitive> getCompletePrimitives(DataSet ds) { 178 107 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>(); 179 108 for (OsmPrimitive primitive : ds.nodes) { 180 if (!primitive.incomplete && primitive.isNew()) {109 if (!primitive.incomplete && !primitive.isNew()) { 181 110 ret.add(primitive); 182 111 } 183 112 } 184 113 for (OsmPrimitive primitive : ds.ways) { 185 if (! primitive.incomplete &&primitive.isNew()) {114 if (!primitive.incomplete && !primitive.isNew()) { 186 115 ret.add(primitive); 187 116 } 188 117 } 189 118 for (OsmPrimitive primitive : ds.relations) { 190 if (! primitive.incomplete &&primitive.isNew()) {119 if (!primitive.incomplete && !primitive.isNew()) { 191 120 ret.add(primitive); 192 121 } … … 196 125 197 126 /** 198 * Updates the local state of a set of primitives (given by a set of primitive 199 * ids) with thestate currently held on the server.200 * 127 * Updates the local state of a set of primitives (given by a set of primitive ids) with the 128 * state currently held on the server. 129 * 201 130 * @param potentiallyDeleted a set of ids to check update from the server 202 131 */ … … 208 137 } 209 138 } 210 EventQueue.invokeLater( 211 new Runnable() { 212 public void run() { 213 new UpdateSelectionAction().updatePrimitives(toSelect); 214 } 215 } 139 EventQueue.invokeLater(new Runnable() { 140 public void run() { 141 new UpdateSelectionAction().updatePrimitives(toSelect); 142 } 143 }); 144 } 145 146 /** 147 * Processes a set of primitives (given by a set of their ids) which might be deleted on the 148 * server. First prompts the user whether he wants to check the current state on the server. If 149 * yes, retrieves the current state on the server and checks whether the primitives are indeed 150 * deleted on the server. 151 * 152 * @param potentiallyDeleted a set of primitives (given by their ids) 153 */ 154 protected void handlePotentiallyDeletedPrimitives(Set<OsmPrimitive> potentiallyDeleted) { 155 ButtonSpec[] options = new ButtonSpec[] { 156 new ButtonSpec( 157 tr("Check on the server"), 158 ImageProvider.get("ok"), 159 tr("Click to check whether objects in your local dataset are deleted on the server"), 160 null /* no specific help topic */ 161 ), 162 new ButtonSpec( 163 tr("Ignore"), 164 ImageProvider.get("cancel"), 165 tr("Click to abort and to resume editing"), 166 null /* no specific help topic */ 167 ), 168 }; 169 170 String message = tr("<html>" + "There are {0} primitives in your local dataset which<br>" 171 + "might be deleted on the server. If you later try to delete or<br>" 172 + "update them the server is likely to report a<br>" + "conflict.<br>" + "<br>" 173 + "Click <strong>{1}</strong> to check the state of these primitives<br>" + "on the server.<br>" 174 + "Click <strong>{2}</strong> to ignore.<br>" + "</html>", 175 potentiallyDeleted.size(), 176 options[0].text, 177 options[1].text 178 ); 179 180 int ret = HelpAwareOptionPane.showOptionDialog( 181 Main.parent, 182 message, 183 tr("Deleted or moved primitives"), 184 JOptionPane.WARNING_MESSAGE, 185 null, 186 options, 187 options[0], 188 ht("/Action/UpdateData#SyncPotentiallyDeletedObjects") 216 189 ); 217 } 218 219 /** 220 * Processes a set of primitives (given by a set of their ids) which might be 221 * deleted on the server. First prompts the user whether he wants to check 222 * the current state on the server. If yes, retrieves the current state on the server 223 * and checks whether the primitives are indeed deleted on the server. 224 * 225 * @param potentiallyDeleted a set of primitives (given by their ids) 226 */ 227 protected void handlePotentiallyDeletedPrimitives(Set<OsmPrimitive> potentiallyDeleted) { 228 String [] options = { 229 "Check on the server", 230 "Ignore" 231 }; 232 233 String message = tr("<html>" 234 + "There are {0} primitives in your local dataset which<br>" 235 + "might be deleted on the server. If you later try to delete or<br>" 236 + "update them the server is likely to report a<br>" 237 + "conflict.<br>" 238 + "<br>" 239 + "Click <strong>{1}</strong> to check the state of these primitives<br>" 240 + "on the server.<br>" 241 + "Click <strong>{2}</strong> to ignore.<br>" 242 + "</html>", 243 potentiallyDeleted.size(), options[0], options[1] 244 ); 245 246 int ret =JOptionPane.showOptionDialog( 247 Main.parent, 248 message, 249 tr("Deleted or moved primitives"), 250 JOptionPane.YES_NO_OPTION, 251 JOptionPane.WARNING_MESSAGE, 252 null, 253 options, 254 options[0] 255 ); 256 switch(ret) { 257 case JOptionPane.CLOSED_OPTION: return; 258 case JOptionPane.NO_OPTION: return; 259 case JOptionPane.YES_OPTION: updatePotentiallyDeletedPrimitives(potentiallyDeleted); break; 260 } 190 if (ret != 0 /* OK */) 191 return; 192 193 updatePotentiallyDeletedPrimitives(potentiallyDeleted); 261 194 } 262 195 263 196 /** 264 197 * Replies the set of primitive ids which have been downloaded by this task list 265 * 198 * 266 199 * @return the set of primitive ids which have been downloaded by this task list 267 200 */ … … 269 202 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>(); 270 203 for (DownloadTask task : osmTasks) { 271 if (task instanceof DownloadOsmTask) {272 DataSet ds = ((DownloadOsmTask) task).getDownloadedData();204 if (task instanceof DownloadOsmTask) { 205 DataSet ds = ((DownloadOsmTask) task).getDownloadedData(); 273 206 if (ds != null) { 274 207 ret.addAll(ds.nodes); … … 280 213 return ret; 281 214 } 215 216 class PostDownloadProcessor implements Runnable { 217 /** 218 * Grabs and displays the error messages after all download threads have finished. 219 */ 220 public void run() { 221 progressMonitor.finishTask(); 222 223 // wait for all download tasks to finish 224 // 225 for (Future<?> future : osmTaskFutures) { 226 try { 227 future.get(); 228 } catch (Exception e) { 229 e.printStackTrace(); 230 return; 231 } 232 } 233 LinkedHashSet<Object> errors = new LinkedHashSet<Object>(); 234 for (DownloadTask dt : osmTasks) { 235 errors.addAll(dt.getErrorObjects()); 236 } 237 if (!errors.isEmpty()) { 238 StringBuffer sb = new StringBuffer(); 239 for (Object error : errors) { 240 if (error instanceof String) { 241 sb.append("<li>").append(error).append("</li>").append("<br>"); 242 } else if (error instanceof Exception) { 243 sb.append("<li>").append(ExceptionUtil.explainException((Exception) error)).append("</li>") 244 .append("<br>"); 245 } 246 } 247 sb.insert(0, "<ul>"); 248 sb.append("</ul>"); 249 250 JOptionPane.showMessageDialog(Main.parent, "<html>" 251 + tr("The following errors occurred during mass download: {0}", sb.toString()) + "</html>", 252 tr("Errors during Download"), JOptionPane.ERROR_MESSAGE); 253 return; 254 } 255 256 // FIXME: this is a hack. We assume that the user canceled the whole download if at 257 // least 258 // one task was canceled or if it failed 259 // 260 for (DownloadTask task : osmTasks) { 261 if (task instanceof DownloadOsmTask) { 262 DownloadOsmTask osmTask = (DownloadOsmTask) task; 263 if (osmTask.isCanceled() || osmTask.isFailed()) 264 return; 265 } 266 } 267 final OsmDataLayer editLayer = Main.map.mapView.getEditLayer(); 268 if (editLayer != null) { 269 Set<OsmPrimitive> myPrimitives = getCompletePrimitives(editLayer.data); 270 for (DownloadTask task : osmTasks) { 271 if (task instanceof DownloadOsmTask) { 272 DataSet ds = ((DownloadOsmTask) task).getDownloadedData(); 273 if (ds != null) { 274 myPrimitives.removeAll(ds.nodes); 275 myPrimitives.removeAll(ds.ways); 276 myPrimitives.removeAll(ds.relations); 277 } 278 } 279 } 280 if (!myPrimitives.isEmpty()) { 281 handlePotentiallyDeletedPrimitives(myPrimitives); 282 } 283 } 284 } 285 } 282 286 } -
trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
r2308 r2325 4 4 5 5 import static org.openstreetmap.josm.tools.I18n.marktr; 6 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 6 7 import static org.openstreetmap.josm.tools.I18n.tr; 7 8 import static org.openstreetmap.josm.tools.I18n.trn; … … 62 63 import org.openstreetmap.josm.data.osm.visitor.MergeVisitor; 63 64 import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor; 65 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 64 66 import org.openstreetmap.josm.gui.MapView; 67 import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec; 65 68 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 66 69 import org.openstreetmap.josm.gui.dialogs.LayerListPopup; … … 334 337 ); 335 338 String msg2 = trn( 336 "{0} object has been purgedfrom the local dataset because it is deleted on the server.",337 "{0} objects have been purgedfrom the local dataset because they are deleted on the server.",339 "{0} conflict has been <strong>resolved automatically</strong> by purging {0} object<br>from the local dataset because it is deleted on the server.", 340 "{0} conflicts have been <strong>resolved automatically</strong> by purging {0} objects<br> from the local dataset because they are deleted on the server.", 338 341 numPurgedPrimitives, 339 342 numPurgedPrimitives 340 343 ); 344 int numRemainingConflicts = numNewConflicts - numPurgedPrimitives; 345 String msg3 = ""; 346 if (numRemainingConflicts >0) { 347 msg3 = trn( 348 "{0} conflict remains to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve it.", 349 "{0} conflicts remain to be resolved.<br><br>Please open the Conflict List Dialog and manually resolve them.", 350 numRemainingConflicts, 351 numRemainingConflicts 352 ); 353 } 354 341 355 StringBuffer sb = new StringBuffer(); 342 356 sb.append("<html>").append(msg1); … … 344 358 sb.append("<br>").append(msg2); 345 359 } 346 sb.append("<br>").append(tr("Please consult the Conflict List Dialog<br>and manually resolve them.")); 360 if (numRemainingConflicts > 0) { 361 sb.append("<br>").append(msg3); 362 } 347 363 sb.append("</html>"); 348 364 if (numNewConflicts > 0) { 349 JButton[] options = new JButton[] { 350 new JButton(tr("OK")), 351 new JButton(tr("Help")) 365 ButtonSpec[] options = new ButtonSpec[] { 366 new ButtonSpec( 367 tr("OK"), 368 ImageProvider.get("ok"), 369 tr("Click to close this dialog and continue editing"), 370 null /* no specific help */ 371 ) 352 372 }; 353 options[0].setIcon(ImageProvider.get("ok")); 354 options[1].setIcon(ImageProvider.get("help")); 355 final JOptionPane pane = new JOptionPane( 373 HelpAwareOptionPane.showOptionDialog( 374 Main.parent, 356 375 sb.toString(), 376 tr("Conflicts detected"), 357 377 JOptionPane.WARNING_MESSAGE, 358 JOptionPane.DEFAULT_OPTION, 359 null, 378 null, /* no icon */ 360 379 options, 361 options[0] 362 ); 363 final JDialog dialog = new JDialog( 364 JOptionPane.getFrameForComponent(Main.parent), 365 tr("Conflicts detected"), 366 true); 367 options[0].addActionListener( 368 new ActionListener() { 369 public void actionPerformed(ActionEvent e) { 370 dialog.setVisible(false); 371 } 372 } 373 ); 374 options[1].addActionListener( 375 new ActionListener() { 376 public void actionPerformed(ActionEvent e) { 377 HelpBrowser b = new HelpBrowser(); 378 b.openHelpTopic("Help/Concepts/Conflict"); 379 b.setVisible(true); 380 } 381 } 382 ); 383 dialog.setContentPane(pane); 384 dialog.pack(); 385 HelpUtil.setHelpContext(dialog.getRootPane(), "/Concepts/Conflict"); 386 WindowGeometry.centerOnScreen(dialog.getSize()).applySafe(dialog); 387 dialog.setVisible(true); 380 options[0], 381 ht("/Concepts/Conflict#WarningAboutDetectedConflicts") 382 ); 388 383 } 389 384 }
Note:
See TracChangeset
for help on using the changeset viewer.