Performance improvement:
authorNiki Roo <niki@nikiroo.be>
Tue, 29 Mar 2016 18:49:35 +0000 (20:49 +0200)
committerNiki Roo <niki@nikiroo.be>
Tue, 29 Mar 2016 18:49:35 +0000 (20:49 +0200)
- much, much better at writing big ammount of data into VCF
- uses compressed jpeg instead of uncompressed png with images
- sends data over the wire in a much more efficient way
- aBook format not improved (no binary, small ammount of text only)

13 files changed:
src/be/nikiroo/jvcard/Card.java
src/be/nikiroo/jvcard/Contact.java
src/be/nikiroo/jvcard/launcher/Main.java
src/be/nikiroo/jvcard/parsers/AbookParser.java
src/be/nikiroo/jvcard/parsers/Parser.java
src/be/nikiroo/jvcard/parsers/Vcard21Parser.java
src/be/nikiroo/jvcard/remote/Server.java
src/be/nikiroo/jvcard/remote/SimpleSocket.java
src/be/nikiroo/jvcard/remote/Sync.java
src/be/nikiroo/jvcard/resources/StringUtils.java
src/be/nikiroo/jvcard/tui/MainWindow.java
src/be/nikiroo/jvcard/tui/panes/ContactDetailsRaw.java
src/be/nikiroo/jvcard/tui/panes/ContactList.java

index 547535804b8f37fa80fb5dc3ca22f89afc22857e..0a405bee47d744e6545b3360579343fdc5466806 100644 (file)
@@ -97,7 +97,7 @@ public class Card extends BaseClass<Contact> {
                        return false;
 
                BufferedWriter writer = new BufferedWriter(new FileWriter(file));
-               writer.append(toString(format));
+               Parser.write(writer, format, this);
                writer.close();
 
                if (this.file != null
@@ -140,24 +140,6 @@ public class Card extends BaseClass<Contact> {
                return true;
        }
 
-       /**
-        * Return a {@link String} representation of this {@link Card} in the given
-        * {@link Format}.
-        * 
-        * @param format
-        *            the {@link Format} to use
-        * 
-        * @return the {@link String}
-        */
-       public String toString(Format format) {
-               StringBuilder builder = new StringBuilder();
-               for (String line : Parser.toStrings(this, format)) {
-                       builder.append(line);
-                       builder.append("\r\n");
-               }
-               return builder.toString();
-       }
-
        /**
         * Return the name of this card (the name of the {@link File} which it was
         * opened from).
@@ -186,6 +168,15 @@ public class Card extends BaseClass<Contact> {
                return file;
        }
 
+       /**
+        * Break the link between this {@link Card} and he {@link File} which was
+        * used to open it if any.
+        */
+       public void unlink() {
+               file = null;
+               lastModified = -1;
+       }
+
        /**
         * Return the date of the last modification for this {@link Card} (or -1 if
         * unknown/new).
@@ -198,7 +189,7 @@ public class Card extends BaseClass<Contact> {
 
        @Override
        public String toString() {
-               return toString(Format.VCard21);
+               return "[Card: " + name + "]";
        }
 
        @Override
index 4b46eab8afa3dcc6aa840d8c89952d0c4ef8b3b5..9facbcd0f38cf45fe06c09f9d92f44e049c9d19d 100644 (file)
@@ -88,27 +88,6 @@ public class Contact extends BaseClass<Data> {
                return found;
        }
 
-       /**
-        * Return a {@link String} representation of this contact.
-        * 
-        * @param format
-        *            the {@link Format} to use
-        * @param startingBKey
-        *            the starting BKey or -1 for no BKeys
-        * @return the {@link String} representation
-        */
-       public String toString(Format format, int startingBKey) {
-               updateBKeys(false);
-
-               StringBuilder builder = new StringBuilder();
-               for (String line : Parser.toStrings(this, format, startingBKey)) {
-                       builder.append(line);
-                       builder.append("\r\n");
-               }
-
-               return builder.toString();
-       }
-
        /**
         * Return a {@link String} representation of this contact formated
         * accordingly to the given format.
@@ -400,7 +379,11 @@ public class Contact extends BaseClass<Data> {
                                        value = ff.get(fieldNum);
                                }
                        } else {
-                               value = getPreferredDataValue(field);
+                               // we don't need the *data* in binary mode...
+                               if (binary)
+                                       value = getData(field).size() > 0 ? "x" : null;
+                               else
+                                       value = getPreferredDataValue(field);
                        }
 
                        if (value == null) {
@@ -527,7 +510,7 @@ public class Contact extends BaseClass<Data> {
         */
        @Override
        public String toString() {
-               return toString(Format.VCard21, -1);
+               return "[Contact: " + getPreferredDataValue("FN") + "]";
        }
 
        /**
index 080223d07251b8b54e561c5b917e2dbe477def19..eeeae4153a57eada0b58e04da065ea2d119101bc 100644 (file)
@@ -63,7 +63,7 @@ public class Main {
         * @return the translated text with the given value where required
         */
        static public String trans(StringId id, Object... values) {
-               return transService.getString(id, (Object[]) values);
+               return transService.getString(id, values);
        }
 
        /**
@@ -278,6 +278,7 @@ public class Main {
                                new RemoteBundle().updateFile(dir);
                        } catch (IOException e) {
                                e.printStackTrace();
+                               System.err.flush();
                                System.exit(ERR_INTERNAL);
                        }
                        break;
@@ -331,7 +332,7 @@ public class Main {
 
                                                                List<TypeInfo> types = new LinkedList<TypeInfo>();
                                                                types.add(new TypeInfo("ENCODING", "b"));
-                                                               types.add(new TypeInfo("TYPE", "png"));
+                                                               types.add(new TypeInfo("TYPE", "jpeg"));
                                                                Data photo = new Data(types, "PHOTO", b64, null);
                                                                contact.add(photo);
                                                        } catch (IOException e) {
@@ -632,6 +633,7 @@ public class Main {
                else
                        System.err.println(trans(err, trans(suberr, subvalues)));
 
+               System.err.flush();
                System.exit(CODE);
        }
 }
index cb4f667119be22b0b8cf8713a1b7f439511c30a4..b8e6e58e47c2187acf5fd80e8b3c046acacf6d33 100644 (file)
@@ -1,5 +1,6 @@
 package be.nikiroo.jvcard.parsers;
 
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -132,4 +133,44 @@ public class AbookParser {
 
                return lines;
        }
+
+       /**
+        * Write the given {@link Contact} in the {@link Appendable}.
+        * 
+        * @param writer
+        *            the {@link Appendable}
+        * @param contact
+        *            the {@link Contact} to write
+        * @param startingBKey
+        *            the starting BKey number (all the other will follow) or -1 for
+        *            no BKey
+        * 
+        * @throws IOException
+        *             in case of IO error
+        */
+       public static void write(Appendable writer, Contact contact,
+                       int startingBKey) throws IOException {
+               for (String s : toStrings(contact, startingBKey)) {
+                       writer.append(s);
+                       writer.append('\n');
+               }
+       }
+
+       /**
+        * Write the given {@link Card} in the {@link Appendable}.
+        * 
+        * @param writer
+        *            the {@link Appendable}
+        * @param card
+        *            the {@link Card} to write
+        * 
+        * @throws IOException
+        *             in case of IO error
+        */
+       public static void write(Appendable writer, Card card) throws IOException {
+               for (String s : toStrings(card)) {
+                       writer.append(s);
+                       writer.append('\n');
+               }
+       }
 }
index ceb35dccca75de055917b4050b5df3f912110fb3..040cd3e113ab9862b15ace9c3967bfca4610878b 100644 (file)
@@ -73,24 +73,27 @@ public class Parser {
        }
 
        /**
-        * Return a {@link String} representation of the given {@link Card}, line by
-        * line.
+        * Write the given {@link Card} in the {@link Appendable}.
         * 
+        * @param writer
+        *            the {@link Appendable}
         * @param card
-        *            the card to convert
-        * 
+        *            the {@link Card} to write
         * @param format
-        *            the output {@link Format} to use
+        *            the {@link Format} to export to
         * 
-        * @return the {@link String} representation
+        * @throws IOException
+        *             in case of IO error
         */
-       public static List<String> toStrings(Card card, Format format) {
+       public static void write(Appendable writer, Format format, Card card)
+                       throws IOException {
                switch (format) {
                case VCard21:
-                       return Vcard21Parser.toStrings(card);
+                       Vcard21Parser.write(writer, card);
+                       break;
                case Abook:
-                       return AbookParser.toStrings(card);
-
+                       AbookParser.write(writer, card);
+                       break;
                default:
                        throw new InvalidParameterException("Unknown format: "
                                        + format.toString());
@@ -98,29 +101,30 @@ public class Parser {
        }
 
        /**
-        * Return a {@link String} representation of the given {@link Card}, line by
-        * line.
-        * 
-        * @param card
-        *            the card to convert
+        * Write the given {@link Contact} in the {@link Appendable}.
         * 
+        * @param writer
+        *            the {@link Appendable}
+        * @param contact
+        *            the {@link Contact} to write
         * @param startingBKey
         *            the starting BKey number (all the other will follow) or -1 for
         *            no BKey
-        * 
         * @param format
-        *            the output {@link Format} to use
+        *            the {@link Format} to export to
         * 
-        * @return the {@link String} representation
+        * @throws IOException
+        *             in case of IO error
         */
-       public static List<String> toStrings(Contact contact, Format format,
-                       int startingBKey) {
+       public static void write(Appendable writer, Contact contact, Format format,
+                       int startingBKey) throws IOException {
                switch (format) {
                case VCard21:
-                       return Vcard21Parser.toStrings(contact, startingBKey);
+                       Vcard21Parser.write(writer, contact, startingBKey);
+                       break;
                case Abook:
-                       return AbookParser.toStrings(contact, startingBKey);
-
+                       AbookParser.write(writer, contact, startingBKey);
+                       break;
                default:
                        throw new InvalidParameterException("Unknown format: "
                                        + format.toString());
index 5388783a48cda3bd75ddfb7d199d8ceaa92fcf89..5a07903ae8ca1a558abe78e64ec873ae91f76d5b 100644 (file)
@@ -1,5 +1,8 @@
 package be.nikiroo.jvcard.parsers;
 
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -134,62 +137,59 @@ public class Vcard21Parser {
        }
 
        /**
-        * Return a {@link String} representation of the given {@link Card}, line by
-        * line.
+        * Write the given {@link Card} in the {@link Appendable}.
         * 
+        * @param writer
+        *            the {@link Appendable}
         * @param card
-        *            the card to convert
+        *            the {@link Card} to write
         * 
-        * @return the {@link String} representation
+        * @throws IOException
+        *             in case of IO error
         */
-       public static List<String> toStrings(Card card) {
-               List<String> lines = new LinkedList<String>();
-
+       public static void write(Appendable writer, Card card) throws IOException {
                for (Contact contact : card) {
-                       lines.addAll(toStrings(contact, -1));
+                       write(writer, contact, -1);
                }
-
-               return lines;
        }
 
        /**
-        * Return a {@link String} representation of the given {@link Contact}, line
-        * by line.
-        * 
-        * @param card
-        *            the contact to convert
+        * Write the given {@link Contact} in the {@link Appendable}.
         * 
+        * @param writer
+        *            the {@link Appendable}
+        * @param contact
+        *            the {@link Contact} to write
         * @param startingBKey
         *            the starting BKey number (all the other will follow) or -1 for
         *            no BKey
         * 
-        * @return the {@link String} representation
+        * @throws IOException
+        *             in case of IO error
         */
-       public static List<String> toStrings(Contact contact, int startingBKey) {
-               List<String> lines = new LinkedList<String>();
+       public static void write(Appendable writer, Contact contact,
+                       int startingBKey) throws IOException {
 
-               lines.add("BEGIN:VCARD");
-               lines.add("VERSION:2.1");
+               writer.append("BEGIN:VCARD\r\n");
+               writer.append("VERSION:2.1\r\n");
                for (Data data : contact) {
-                       lines.addAll(toStrings(data));
+                       write(writer, data);
                }
-               lines.add("END:VCARD");
-
-               return lines;
+               writer.append("END:VCARD\r\n");
        }
 
        /**
-        * Return a {@link String} representation of the given {@link Data}, line by
-        * line.
+        * Write the given {@link Data} in the {@link Appendable}.
         * 
+        * @param writer
+        *            the {@link Appendable}
         * @param data
-        *            the data to convert
+        *            the {@link Data} to write
         * 
-        * @return the {@link String} representation
+        * @throws IOException
+        *             in case of IO error
         */
-       public static List<String> toStrings(Data data) {
-               List<String> lines = new LinkedList<String>();
-
+       public static void write(Appendable writer, Data data) throws IOException {
                StringBuilder dataBuilder = new StringBuilder();
                if (data.getGroup() != null && !data.getGroup().trim().equals("")) {
                        dataBuilder.append(data.getGroup().trim());
@@ -212,31 +212,25 @@ public class Vcard21Parser {
                // RFC says: Content lines SHOULD be folded to a maximum width of 75
                // octets -> since it is SHOULD, we will just cut it as 74/75 chars
                // depending if the last one fits in one char (note: chars != octet)
-               boolean continuation = false;
-               while (dataBuilder.length() > 0) {
-                       int stop = 74;
-                       if (continuation)
-                               stop--; // the space takes 1
-                       if (dataBuilder.length() > stop) {
-                               char car = dataBuilder.charAt(stop - 1);
+               int previous = 0;
+               for (int index = 0; index < dataBuilder.length(); previous = index) {
+                       index += 74;
+                       if (previous > 0)
+                               index--; // the space takes 1
+                       if (dataBuilder.length() > index) {
+                               char car = dataBuilder.charAt(index - 1);
                                // RFC forbids cutting a character in 2
                                if (Character.isHighSurrogate(car)) {
-                                       stop++;
+                                       index++;
                                }
                        }
 
-                       stop = Math.min(stop, dataBuilder.length());
-                       if (continuation) {
-                               lines.add(' ' + dataBuilder.substring(0, stop));
-                       } else {
-                               lines.add(dataBuilder.substring(0, stop));
-                       }
-                       dataBuilder.delete(0, stop);
-
-                       continuation = true;
+                       index = Math.min(index, dataBuilder.length());
+                       if (previous > 0)
+                               writer.append(' ');
+                       writer.append(dataBuilder, previous, index);
+                       writer.append("\r\n");
                }
-
-               return lines;
        }
 
        /**
@@ -248,7 +242,20 @@ public class Vcard21Parser {
         * @return the clone {@link Contact}
         */
        public static Card clone(Card c) {
-               return new Card(parseContact(toStrings(c)));
+               try {
+                       File tmp = File.createTempFile("clone", ".vcf");
+                       c.saveAs(tmp, Format.VCard21);
+
+                       Card clone = new Card(tmp, Format.VCard21);
+                       clone.unlink();
+                       tmp.delete();
+
+                       return clone;
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+
+               return null;
        }
 
        /**
@@ -261,7 +268,22 @@ public class Vcard21Parser {
         * @return the clone {@link Contact}
         */
        public static Contact clone(Contact c) {
-               return parseContact(toStrings(c, -1)).get(0);
+               try {
+                       File tmp = File.createTempFile("clone", ".vcf");
+                       FileWriter writer = new FileWriter(tmp);
+                       write(writer, c, -1);
+                       writer.close();
+
+                       Card clone = new Card(tmp, Format.VCard21);
+                       clone.unlink();
+                       tmp.delete();
+
+                       return clone.remove(0);
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+
+               return null;
        }
 
        /**
index 962f2d00133069eee26205f97e23205373b86e44..ac29e972a562fe94685358c909221a9ffd38d119 100644 (file)
@@ -17,6 +17,7 @@ import be.nikiroo.jvcard.Contact;
 import be.nikiroo.jvcard.Data;
 import be.nikiroo.jvcard.parsers.Format;
 import be.nikiroo.jvcard.parsers.Vcard21Parser;
+import be.nikiroo.jvcard.remote.SimpleSocket.BlockAppendable;
 import be.nikiroo.jvcard.resources.StringUtils;
 import be.nikiroo.jvcard.resources.bundles.RemoteBundle;
 import be.nikiroo.jvcard.resources.enums.RemotingOption;
@@ -323,7 +324,7 @@ public class Server implements Runnable {
 
                switch (command) {
                case GET_CARD: {
-                       s.sendBlock(doGetCard(name));
+                       sendCardBlock(s, name);
                        break;
                }
                case POST_CARD: {
@@ -405,10 +406,13 @@ public class Server implements Runnable {
                switch (command) {
                case GET_CONTACT: {
                        Contact contact = card.getById(cmd.getParam());
-                       if (contact != null)
-                               s.sendBlock(Vcard21Parser.toStrings(contact, -1));
-                       else
+                       if (contact != null) {
+                               BlockAppendable app = s.createBlockAppendable();
+                               Vcard21Parser.write(app, contact, -1);
+                               app.close();
+                       } else {
                                s.sendBlock();
+                       }
                        break;
                }
                case POST_CONTACT: {
@@ -516,9 +520,9 @@ public class Server implements Runnable {
                case GET_DATA: {
                        for (Data data : contact) {
                                if (data.getName().equals(cmd.getParam())) {
-                                       for (String line : Vcard21Parser.toStrings(data)) {
-                                               s.send(line);
-                                       }
+                                       BlockAppendable app = s.createBlockAppendable();
+                                       Vcard21Parser.write(app, data);
+                                       // note: we do NOT close 'app', since it would send an EOB
                                }
                        }
                        s.sendBlock();
@@ -602,20 +606,19 @@ public class Server implements Runnable {
         * @throws IOException
         *             in case of error
         */
-       private List<String> doGetCard(String name) throws IOException {
-               List<String> lines = new LinkedList<String>();
-
+       private void sendCardBlock(SimpleSocket s, String name) throws IOException {
                File vcf = getFile(name);
+               BlockAppendable app = s.createBlockAppendable();
 
                if (vcf != null && vcf.exists()) {
                        Card card = new Card(vcf, Format.VCard21);
 
                        // timestamp + data
-                       lines.add(StringUtils.fromTime(card.getLastModified()));
-                       lines.addAll(Vcard21Parser.toStrings(card));
+                       app.append(StringUtils.fromTime(card.getLastModified()) + "\r\n");
+                       Vcard21Parser.write(app, card);
                }
 
-               return lines;
+               app.close();
        }
 
        /**
index d9dcb6007f8c6050126b97960c4a755ab8e305c2..264fff5c68b458e6a12e45c315da306cb0b04f1e 100644 (file)
@@ -1,6 +1,7 @@
 package be.nikiroo.jvcard.remote;
 
 import java.io.BufferedReader;
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
@@ -19,6 +20,53 @@ import java.util.List;
  * @author niki
  */
 public class SimpleSocket {
+       /**
+        * An {@link Appendable} that can be used to send data over a
+        * {@link SimpleSocket}. You must close it to send the end of block element.
+        * 
+        * @author niki
+        *
+        */
+       public class BlockAppendable implements Appendable, Closeable {
+               private SimpleSocket ss;
+
+               /**
+                * Create a new {@link BlockAppendable} for the given
+                * {@link SimpleSocket}.
+                * 
+                * @param ss
+                *            the {@link SimpleSocket}
+                */
+               public BlockAppendable(SimpleSocket ss) {
+                       this.ss = ss;
+               }
+
+               @Override
+               public Appendable append(CharSequence csq) throws IOException {
+                       ss.send(csq);
+                       return this;
+               }
+
+               @Override
+               public Appendable append(char c) throws IOException {
+                       ss.send("" + c);
+                       return this;
+               }
+
+               @Override
+               public Appendable append(CharSequence csq, int start, int end)
+                               throws IOException {
+                       ss.send(csq.subSequence(start, end));
+                       return this;
+               }
+
+               @Override
+               public void close() throws IOException {
+                       ss.sendBlock();
+               }
+
+       }
+
        /**
         * The current version of the network protocol.
         */
@@ -141,12 +189,12 @@ public class SimpleSocket {
         * @throws IOException
         *             in case of IO error
         */
-       protected void send(String data) throws IOException {
+       protected void send(CharSequence data) throws IOException {
                if (data != null) {
-                       out.write(data);
+                       out.append(data);
                }
 
-               out.write("\n");
+               out.append("\n");
 
                if (out.checkError())
                        throw new IOException();
@@ -220,7 +268,19 @@ public class SimpleSocket {
         *             in case of IO error
         */
        public void sendCommand(Command command, String param) throws IOException {
-               sendLine(new CommandInstance(command, param, CURRENT_VERSION).toString());
+               sendLine(new CommandInstance(command, param, CURRENT_VERSION)
+                               .toString());
+       }
+
+       /**
+        * Create a new {@link Appendable} that can be used to send data on this
+        * {@link SimpleSocket}. When you are done, just call
+        * {@link BlockAppendable#close()}.
+        * 
+        * @return the {@link Appendable}
+        */
+       public BlockAppendable createBlockAppendable() {
+               return new BlockAppendable(this);
        }
 
        /**
index 609041eaaceef39e449df33a7d85781b99f6c2ab..a1e5e2429cc75f5a7b35a854e440773df34cf6fb 100644 (file)
@@ -24,6 +24,7 @@ import be.nikiroo.jvcard.launcher.CardResult;
 import be.nikiroo.jvcard.launcher.CardResult.MergeCallback;
 import be.nikiroo.jvcard.parsers.Format;
 import be.nikiroo.jvcard.parsers.Vcard21Parser;
+import be.nikiroo.jvcard.remote.SimpleSocket.BlockAppendable;
 import be.nikiroo.jvcard.resources.StringUtils;
 import be.nikiroo.jvcard.resources.bundles.RemoteBundle;
 import be.nikiroo.jvcard.resources.enums.RemotingOption;
@@ -276,7 +277,9 @@ public class Sync {
                                }
                                case POST_CARD: {
                                        s.sendCommand(Command.POST_CARD);
-                                       s.sendBlock(Vcard21Parser.toStrings(local));
+                                       BlockAppendable app = s.createBlockAppendable();
+                                       Vcard21Parser.write(app, local);
+                                       app.close();
                                        local.saveAs(getCache(cacheDirOrig), Format.VCard21);
                                        setLastModified(s.receiveLine());
                                        break;
@@ -343,7 +346,9 @@ public class Sync {
                                        // ...but without starting with original since it is not
                                        // true here
                                        s.sendCommand(Command.POST_CARD);
-                                       s.sendBlock(Vcard21Parser.toStrings(merge));
+                                       BlockAppendable app = s.createBlockAppendable();
+                                       Vcard21Parser.write(app, merge);
+                                       app.close();
                                        String serverLastModifTime = s.receiveLine();
                                        //
 
@@ -409,7 +414,9 @@ public class Sync {
                }
                for (Contact c : added) {
                        s.sendCommand(Command.POST_CONTACT, c.getId());
-                       s.sendBlock(Vcard21Parser.toStrings(c, -1));
+                       BlockAppendable app = s.createBlockAppendable();
+                       Vcard21Parser.write(app, c, -1);
+                       s.close();
                }
                if (from.size() > 0) {
                        for (int index = 0; index < from.size(); index++) {
@@ -425,7 +432,9 @@ public class Sync {
                                }
                                for (Data d : subadded) {
                                        s.sendCommand(Command.POST_DATA, d.getContentState(true));
-                                       s.sendBlock(Vcard21Parser.toStrings(d));
+                                       BlockAppendable app = s.createBlockAppendable();
+                                       Vcard21Parser.write(app, d);
+                                       app.close();
                                }
                                s.sendCommand(Command.PUT_CONTACT);
                        }
index cee9fb62715158ec6c2479ea01da4975a84c1159..e9203d5b5226b37d52fe102622f49ca729ba4f0b 100644 (file)
@@ -194,7 +194,7 @@ public class StringUtils {
                ByteArrayOutputStream out = new ByteArrayOutputStream();
 
                try {
-                       ImageIO.write(image, "png", out);
+                       ImageIO.write(image, "jpeg", out);
                        byte[] imageBytes = out.toByteArray();
 
                        imageString = DatatypeConverter.printBase64Binary(imageBytes);
index 1cbc01412a77f9e7163862e85b007f07e6d3a5b5..a87b7ba9b7b09c393cd2d950810ae0e277fea87b 100644 (file)
@@ -522,7 +522,8 @@ public class MainWindow extends BasicWindow {
 
                        kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_KEY,
                                        keyTrans));
-                       kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC, trans));
+                       kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC,
+                                       trans));
 
                        actionPanel.addComponent(kPane);
                }
@@ -534,8 +535,8 @@ public class MainWindow extends BasicWindow {
                }
 
                if (width > 0) {
-                       actionPanel.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC,
-                                       StringUtils.padString("", width)));
+                       actionPanel.addComponent(UiColors.createLabel(
+                                       ColorOption.ACTION_DESC, StringUtils.padString("", width)));
                }
        }
 
@@ -627,7 +628,7 @@ public class MainWindow extends BasicWindow {
                                setMessage(mess, action.isError());
                        }
 
-                       if (action.onAction()) {
+                       if (!action.isError() && action.onAction()) {
                                handleAction(action, null);
                        }
 
index c47776025f7f17e1d0d32842d0e78b068c8621ec..4a2712d7bd2aca3c88f924d223df3c186a2e84c4 100644 (file)
@@ -42,7 +42,13 @@ public class ContactDetailsRaw extends MainContentList {
                                StringId.KEY_ACTION_EDIT_FIELD) {
                        @Override
                        public Object getObject() {
-                               return getSelectedData();
+                               Data data = getSelectedData();
+                               if (data != null && data.getB64Key() != -1) {
+                                       setMessage("Cannot modify binary values in RAW mode", true);
+                                       data = null;
+                               }
+                               
+                               return data;
                        }
 
                        @Override
@@ -262,6 +268,7 @@ public class ContactDetailsRaw extends MainContentList {
        @Override
        protected List<TextPart> getLabel(int index, int width, boolean selected,
                        boolean focused) {
+
                // TODO: from ini file?
                int SIZE_COL_1 = 15;
                int SIZE_COL_2_OPT = 10;
@@ -296,7 +303,12 @@ public class ContactDetailsRaw extends MainContentList {
 
                StringBuilder valueBuilder = new StringBuilder(" ");
                if (!extMode) {
-                       valueBuilder.append(data.getValue().replaceAll("\n", "\\\\n"));
+                       if (data.getB64Key() != -1) {
+                               // TODO: i18n
+                               valueBuilder.append("<BKey " + data.getB64Key() + ">");
+                       } else {
+                               valueBuilder.append(data.getValue().replaceAll("\n", "\\\\n"));
+                       }
                        if (data.getGroup() != null && data.getGroup().length() > 0) {
                                valueBuilder.append("(");
                                valueBuilder.append(data.getGroup());
index 9001c39f79ba72256e25eee925af7ae8bbb01b12..20d4944c04a74b0fcbb2e24cfe2df16248ec0b66 100644 (file)
@@ -268,7 +268,7 @@ public class ContactList extends MainContentList {
 
                String[] array = contact.toStringArray(format, getSeparator(), " ",
                                width, Main.isUnicode());
-
+               
                if (contact.isDirty()) {
                        parts.add(new TextPart(" ", el));
                        parts.add(new TextPart("*", elDirty));