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 } 119 fireTableDataChanged(); 120 } 121 122 public List<SaveLayerInfo> getSafeLayerInfo() { 123 return this.layerInfo; 124 } 125 126 public List<SaveLayerInfo> getLayersWithoutFilesAndSaveRequest() { 127 List<SaveLayerInfo> ret = new ArrayList<>(); 128 if (layerInfo != null) { 129 for (SaveLayerInfo info: layerInfo) { 130 if (info.isDoSaveToFile() && info.getFile() == null) { 131 ret.add(info); 132 } 133 } 134 } 135 return ret; 136 } 137 138 public List<SaveLayerInfo> getLayersWithIllegalFilesAndSaveRequest() { 139 List<SaveLayerInfo> ret = new ArrayList<>(); 140 if (layerInfo != null) { 141 for (SaveLayerInfo info: layerInfo) { 142 if (info.isDoSaveToFile() && info.getFile() != null && info.getFile().exists() && !info.getFile().canWrite()) { 143 ret.add(info); 144 } 145 } 146 } 147 return ret; 148 } 149 150 public List<SaveLayerInfo> getLayersWithConflictsAndUploadRequest() { 151 List<SaveLayerInfo> ret = new ArrayList<>(); 152 if (layerInfo != null) { 153 for (SaveLayerInfo info: layerInfo) { 154 AbstractModifiableLayer l = info.getLayer(); 155 if (info.isDoUploadToServer() && l instanceof OsmDataLayer && !((OsmDataLayer) l).getConflicts().isEmpty()) { 156 ret.add(info); 157 } 158 } 159 } 160 return ret; 161 } 162 163 public List<SaveLayerInfo> getLayersToUpload() { 164 List<SaveLayerInfo> ret = new ArrayList<>(); 165 if (layerInfo != null) { 166 for (SaveLayerInfo info: layerInfo) { 167 if (info.isDoUploadToServer()) { 168 ret.add(info); 169 } 170 } 171 } 172 return ret; 173 } 174 175 public List<SaveLayerInfo> getLayersToSave() { 176 List<SaveLayerInfo> ret = new ArrayList<>(); 177 if (layerInfo != null) { 178 for (SaveLayerInfo info: layerInfo) { 179 if (info.isDoSaveToFile()) { 180 ret.add(info); 181 } 182 } 183 } 184 return ret; 185 } 186 187 public void setUploadState(AbstractModifiableLayer layer, UploadOrSaveState state) { 188 SaveLayerInfo info = getSaveLayerInfo(layer); 189 if (info != null) { 190 info.setUploadState(state); 191 } 192 fireTableDataChanged(); 193 } 194 195 public void setSaveState(AbstractModifiableLayer layer, UploadOrSaveState state) { 196 SaveLayerInfo info = getSaveLayerInfo(layer); 197 if (info != null) { 198 info.setSaveState(state); 199 } 200 fireTableDataChanged(); 201 } 202 203 public SaveLayerInfo getSaveLayerInfo(AbstractModifiableLayer layer) { 204 for (SaveLayerInfo info: this.layerInfo) { 205 if (info.getLayer() == layer) 206 return info; 207 } 208 return null; 209 } 210 211 public void resetSaveAndUploadState() { 212 for (SaveLayerInfo info: layerInfo) { 213 info.setSaveState(null); 214 info.setUploadState(null); 215 } 216 } 217 218 public boolean hasUnsavedData() { 219 for (SaveLayerInfo info: layerInfo) { 220 if (info.isDoUploadToServer() && !UploadOrSaveState.OK.equals(info.getUploadState())) 221 return true; 222 if (info.isDoSaveToFile() && !UploadOrSaveState.OK.equals(info.getSaveState())) 223 return true; 224 } 225 return false; 226 } 227 228 public int getNumCancel() { 229 int ret = 0; 230 for (SaveLayerInfo info: layerInfo) { 231 if (UploadOrSaveState.CANCELED.equals(info.getSaveState()) 232 || UploadOrSaveState.CANCELED.equals(info.getUploadState())) { 233 ret++; 234 } 235 } 236 return ret; 237 } 238 239 public int getNumFailed() { 240 int ret = 0; 241 for (SaveLayerInfo info: layerInfo) { 242 if (UploadOrSaveState.FAILED.equals(info.getSaveState()) 243 || UploadOrSaveState.FAILED.equals(info.getUploadState())) { 244 ret++; 245 } 246 } 247 return ret; 248 } 249}