001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.io; 003 004import java.beans.PropertyChangeListener; 005import java.beans.PropertyChangeSupport; 006import java.io.File; 007import java.util.ArrayList; 008import java.util.Collections; 009import java.util.Comparator; 010import java.util.List; 011 012import javax.swing.table.DefaultTableModel; 013 014import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 015import org.openstreetmap.josm.gui.layer.OsmDataLayer; 016 017public class SaveLayersModel extends DefaultTableModel { 018 public static final String MODE_PROP = SaveLayerInfo.class.getName() + ".mode"; 019 020 public enum Mode { 021 EDITING_DATA, 022 UPLOADING_AND_SAVING 023 } 024 025 private transient List<SaveLayerInfo> layerInfo; 026 private Mode mode; 027 private final PropertyChangeSupport support; 028 029 // keep in sync with how the columns are ordered in SaveLayersTableColumnModel#build 030 private static final int columnFilename = 0; 031 private static final int columnActions = 2; 032 033 /** 034 * Constructs a new {@code SaveLayersModel}. 035 */ 036 public SaveLayersModel() { 037 mode = Mode.EDITING_DATA; 038 support = new PropertyChangeSupport(this); 039 } 040 041 public void addPropertyChangeListener(PropertyChangeListener l) { 042 support.addPropertyChangeListener(l); 043 } 044 045 public void removePropertyChangeListener(PropertyChangeListener l) { 046 support.removePropertyChangeListener(l); 047 } 048 049 protected void fireModeChanged(Mode oldValue, Mode newValue) { 050 support.firePropertyChange(MODE_PROP, oldValue, newValue); 051 } 052 053 public void setMode(Mode newValue) { 054 Mode oldValue = this.mode; 055 this.mode = newValue; 056 fireModeChanged(oldValue, newValue); 057 } 058 059 public Mode getMode() { 060 return mode; 061 } 062 063 /** 064 * Populates the model with given modifiable layers. 065 * @param layers The layers to use to populate this model 066 * @since 7358 067 */ 068 public void populate(List<? extends AbstractModifiableLayer> layers) { 069 layerInfo = new ArrayList<>(); 070 if (layers == null) return; 071 for (AbstractModifiableLayer layer: layers) { 072 layerInfo.add(new SaveLayerInfo(layer)); 073 } 074 Collections.sort( 075 layerInfo, 076 new Comparator<SaveLayerInfo>() { 077 @Override 078 public int compare(SaveLayerInfo o1, SaveLayerInfo o2) { 079 return o1.compareTo(o2); 080 } 081 } 082 ); 083 fireTableDataChanged(); 084 } 085 086 @Override 087 public int getRowCount() { 088 if (layerInfo == null) return 0; 089 return layerInfo.size(); 090 } 091 092 @Override 093 public Object getValueAt(int row, int column) { 094 if (layerInfo == null) return null; 095 return layerInfo.get(row); 096 } 097 098 @Override 099 public boolean isCellEditable(int row, int column) { 100 return column == columnFilename || column == columnActions; 101 } 102 103 @Override 104 public void setValueAt(Object value, int row, int column) { 105 final SaveLayerInfo info = this.layerInfo.get(row); 106 switch(column) { 107 case columnFilename: 108 info.setFile((File) value); 109 if (info.isSavable()) { 110 info.setDoSaveToFile(true); 111 } 112 break; 113 case columnActions: 114 boolean[] values = (boolean[]) value; 115 info.setDoUploadToServer(values[0]); 116 info.setDoSaveToFile(values[1]); 117 break; 118 default: // Do nothing 119 } 120 fireTableDataChanged(); 121 } 122 123 public List<SaveLayerInfo> getSafeLayerInfo() { 124 return this.layerInfo; 125 } 126 127 public List<SaveLayerInfo> getLayersWithoutFilesAndSaveRequest() { 128 List<SaveLayerInfo> ret = new ArrayList<>(); 129 if (layerInfo != null) { 130 for (SaveLayerInfo info: layerInfo) { 131 if (info.isDoSaveToFile() && info.getFile() == null) { 132 ret.add(info); 133 } 134 } 135 } 136 return ret; 137 } 138 139 public List<SaveLayerInfo> getLayersWithIllegalFilesAndSaveRequest() { 140 List<SaveLayerInfo> ret = new ArrayList<>(); 141 if (layerInfo != null) { 142 for (SaveLayerInfo info: layerInfo) { 143 if (info.isDoSaveToFile() && info.getFile() != null && info.getFile().exists() && !info.getFile().canWrite()) { 144 ret.add(info); 145 } 146 } 147 } 148 return ret; 149 } 150 151 public List<SaveLayerInfo> getLayersWithConflictsAndUploadRequest() { 152 List<SaveLayerInfo> ret = new ArrayList<>(); 153 if (layerInfo != null) { 154 for (SaveLayerInfo info: layerInfo) { 155 AbstractModifiableLayer l = info.getLayer(); 156 if (info.isDoUploadToServer() && l instanceof OsmDataLayer && !((OsmDataLayer) l).getConflicts().isEmpty()) { 157 ret.add(info); 158 } 159 } 160 } 161 return ret; 162 } 163 164 public List<SaveLayerInfo> getLayersToUpload() { 165 List<SaveLayerInfo> ret = new ArrayList<>(); 166 if (layerInfo != null) { 167 for (SaveLayerInfo info: layerInfo) { 168 if (info.isDoUploadToServer()) { 169 ret.add(info); 170 } 171 } 172 } 173 return ret; 174 } 175 176 public List<SaveLayerInfo> getLayersToSave() { 177 List<SaveLayerInfo> ret = new ArrayList<>(); 178 if (layerInfo != null) { 179 for (SaveLayerInfo info: layerInfo) { 180 if (info.isDoSaveToFile()) { 181 ret.add(info); 182 } 183 } 184 } 185 return ret; 186 } 187 188 public void setUploadState(AbstractModifiableLayer layer, UploadOrSaveState state) { 189 SaveLayerInfo info = getSaveLayerInfo(layer); 190 if (info != null) { 191 info.setUploadState(state); 192 } 193 fireTableDataChanged(); 194 } 195 196 public void setSaveState(AbstractModifiableLayer layer, UploadOrSaveState state) { 197 SaveLayerInfo info = getSaveLayerInfo(layer); 198 if (info != null) { 199 info.setSaveState(state); 200 } 201 fireTableDataChanged(); 202 } 203 204 public SaveLayerInfo getSaveLayerInfo(AbstractModifiableLayer layer) { 205 for (SaveLayerInfo info: this.layerInfo) { 206 if (info.getLayer() == layer) 207 return info; 208 } 209 return null; 210 } 211 212 public void resetSaveAndUploadState() { 213 for (SaveLayerInfo info: layerInfo) { 214 info.setSaveState(null); 215 info.setUploadState(null); 216 } 217 } 218 219 public boolean hasUnsavedData() { 220 for (SaveLayerInfo info: layerInfo) { 221 if (info.isDoUploadToServer() && !UploadOrSaveState.OK.equals(info.getUploadState())) 222 return true; 223 if (info.isDoSaveToFile() && !UploadOrSaveState.OK.equals(info.getSaveState())) 224 return true; 225 } 226 return false; 227 } 228 229 public int getNumCancel() { 230 int ret = 0; 231 for (SaveLayerInfo info: layerInfo) { 232 if (UploadOrSaveState.CANCELED.equals(info.getSaveState()) 233 || UploadOrSaveState.CANCELED.equals(info.getUploadState())) { 234 ret++; 235 } 236 } 237 return ret; 238 } 239 240 public int getNumFailed() { 241 int ret = 0; 242 for (SaveLayerInfo info: layerInfo) { 243 if (UploadOrSaveState.FAILED.equals(info.getSaveState()) 244 || UploadOrSaveState.FAILED.equals(info.getUploadState())) { 245 ret++; 246 } 247 } 248 return ret; 249 } 250}