Resources system rewrite + new "--save-config DIR" option
[jvcard.git] / src / be / nikiroo / jvcard / tui / panes / FileList.java
1 package be.nikiroo.jvcard.tui.panes;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.LinkedList;
7 import java.util.List;
8
9 import be.nikiroo.jvcard.Card;
10 import be.nikiroo.jvcard.launcher.CardResult;
11 import be.nikiroo.jvcard.launcher.CardResult.MergeCallback;
12 import be.nikiroo.jvcard.launcher.Main;
13 import be.nikiroo.jvcard.parsers.Format;
14 import be.nikiroo.jvcard.resources.StringUtils;
15 import be.nikiroo.jvcard.resources.enums.ColorOption;
16 import be.nikiroo.jvcard.resources.enums.StringId;
17 import be.nikiroo.jvcard.tui.KeyAction;
18 import be.nikiroo.jvcard.tui.KeyAction.DataType;
19 import be.nikiroo.jvcard.tui.KeyAction.Mode;
20
21 import com.googlecode.lanterna.input.KeyType;
22
23 public class FileList extends MainContentList {
24 private List<String> files;
25 private List<CardResult> cards;
26
27 private FileList merger;
28 private String mergeRemoteState;
29 private String mergeSourceFile;
30 private File mergeTargetFile;
31
32 public FileList(List<String> files) {
33 setFiles(files);
34 }
35
36 /**
37 * Change the list of currently selected files.
38 *
39 * @param files
40 * the new files
41 */
42 public void setFiles(List<String> files) {
43 clearItems();
44 this.files = files;
45 cards = new ArrayList<CardResult>();
46
47 for (String file : files) {
48 addItem(file); // TODO
49 cards.add(null);
50 }
51
52 setSelectedIndex(0);
53 }
54
55 @Override
56 public DataType getDataType() {
57 return DataType.CARD_FILES;
58 }
59
60 @Override
61 protected List<TextPart> getLabel(int index, int width, boolean selected,
62 boolean focused) {
63 // TODO: from ini file?
64 int SIZE_COL_1 = 3;
65
66 ColorOption el = (focused && selected) ? ColorOption.CONTACT_LINE_SELECTED
67 : ColorOption.CONTACT_LINE;
68 ColorOption elSep = (focused && selected) ? ColorOption.CONTACT_LINE_SEPARATOR_SELECTED
69 : ColorOption.CONTACT_LINE_SEPARATOR;
70
71 List<TextPart> parts = new LinkedList<TextPart>();
72
73 String count = "";
74 if (cards.get(index) != null) {
75 try {
76 count += cards.get(index).getCard().size();
77 } catch (IOException e) {
78 }
79 }
80
81 String name = files.get(index).replaceAll("\\\\", "/");
82 int indexSl = name.lastIndexOf('/');
83 if (indexSl >= 0) {
84 name = name.substring(indexSl + 1);
85 }
86
87 name = StringUtils.sanitize(name, Main.isUnicode());
88
89 count = " " + StringUtils.padString(count, SIZE_COL_1) + " ";
90 name = " "
91 + StringUtils.padString(name, width - SIZE_COL_1
92 - getSeparator().length()) + " ";
93
94 parts.add(new TextPart(count, el));
95 parts.add(new TextPart(getSeparator(), elSep));
96 parts.add(new TextPart(name, el));
97
98 return parts;
99 };
100
101 @Override
102 public List<KeyAction> getKeyBindings() {
103 List<KeyAction> actions = new LinkedList<KeyAction>();
104
105 // TODO del, save...
106 actions.add(new KeyAction(Mode.CONTACT_LIST, KeyType.Enter,
107 StringId.KEY_ACTION_VIEW_CARD) {
108 private Object obj = null;
109
110 @Override
111 public Object getObject() {
112 if (obj == null) {
113 int index = getSelectedIndex();
114 if (index < 0 || index >= cards.size())
115 return null;
116
117 try {
118 if (cards.get(index) != null) {
119 obj = cards.get(index).getCard();
120 } else {
121 String file = files.get(index);
122
123 CardResult card = null;
124 final Card arr[] = new Card[4];
125 try {
126 card = Main.getCard(file, new MergeCallback() {
127 @Override
128 public Card merge(Card previous,
129 Card local, Card server,
130 Card autoMerged) {
131 arr[0] = previous;
132 arr[1] = local;
133 arr[2] = server;
134 arr[3] = autoMerged;
135
136 return null;
137 }
138 });
139
140 obj = card.getCard(); // throw IOE if problem
141 } catch (IOException e) {
142 if (arr[0] == null)
143 throw e;
144
145 // merge management: set all merge vars in
146 // merger,
147 // make sure it has cards but mergeTargetFile
148 // does not exist
149 // (create then delete if needed)
150 // TODO: i18n
151 setMessage(
152 "Merge error, please check/fix the merged contact",
153 true);
154
155 // TODO: i18n + filename with numbers in it to
156 // fix
157 File a = File.createTempFile("Merge result ",
158 ".vcf");
159 File p = File.createTempFile(
160 "Previous common version ", ".vcf");
161 File l = File.createTempFile("Local ", ".vcf");
162 File s = File.createTempFile("Remote ", ".vcf");
163 arr[3].saveAs(a, Format.VCard21);
164 arr[0].saveAs(p, Format.VCard21);
165 arr[1].saveAs(l, Format.VCard21);
166 arr[2].saveAs(s, Format.VCard21);
167 List<String> mfiles = new LinkedList<String>();
168 mfiles.add(a.getAbsolutePath());
169 mfiles.add(p.getAbsolutePath());
170 mfiles.add(l.getAbsolutePath());
171 mfiles.add(s.getAbsolutePath());
172 merger = new FileList(mfiles);
173 merger.mergeRemoteState = arr[2]
174 .getContentState(false);
175 merger.mergeSourceFile = files.get(index);
176 merger.mergeTargetFile = a;
177
178 obj = merger;
179 return obj;
180 }
181
182 cards.set(index, card);
183
184 invalidate();
185
186 if (card.isSynchronised()) {
187 // TODO i18n
188 if (card.isChanged())
189 setMessage(
190 "card synchronised: changes from server",
191 false);
192 else
193 setMessage("card synchronised: no changes",
194 false);
195 }
196 }
197 } catch (IOException ioe) {
198 ioe.printStackTrace();
199 // TODO
200 setMessage("ERROR!", true);
201 }
202 }
203
204 return obj;
205 }
206
207 });
208
209 return actions;
210 }
211
212 @Override
213 public String wakeup() throws IOException {
214 String s = super.wakeup();
215 if (s != null)
216 return s;
217
218 if (merger != null) {
219 if (!merger.mergeTargetFile.exists()) {
220 throw new IOException("Merge cancelled");
221 }
222
223 // merge back to server if needed and not changed:
224 try {
225 Main.getCard(merger.mergeSourceFile, new MergeCallback() {
226 @Override
227 public Card merge(Card previous, Card local, Card server,
228 Card autoMerged) {
229 try {
230 if (server.getContentState(false).equals(
231 merger.mergeRemoteState)) {
232 return new Card(merger.mergeTargetFile,
233 Format.VCard21);
234 }
235 } catch (IOException e) {
236 e.printStackTrace();
237 }
238
239 return null;
240 }
241 }).getCard();
242 } catch (Exception e) {
243 e.printStackTrace();
244 throw new IOException("Server changed since merge, cancel", e);
245 }
246
247 merger = null;
248
249 // TODO i18n
250 return "merged.";
251 }
252
253 return null;
254 }
255 }