gui: add a Properties page
authorNiki Roo <niki@nikiroo.be>
Thu, 14 Mar 2019 21:10:08 +0000 (22:10 +0100)
committerNiki Roo <niki@nikiroo.be>
Thu, 14 Mar 2019 21:10:08 +0000 (22:10 +0100)
src/be/nikiroo/fanfix/reader/BasicReader.java
src/be/nikiroo/fanfix/reader/tui/TuiReaderStoryWindow.java
src/be/nikiroo/fanfix/reader/ui/GuiReaderBook.java
src/be/nikiroo/fanfix/reader/ui/GuiReaderFrame.java

index 71f19a101bc8b5b3216b66bc2fea24bcde24f7ee..83f2d3c266db52c936b0fe58d5b99e617d61109a 100644 (file)
@@ -4,6 +4,13 @@ import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map.Entry;
 
 import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.bundles.Config;
@@ -14,6 +21,7 @@ import be.nikiroo.fanfix.library.BasicLibrary;
 import be.nikiroo.fanfix.library.LocalLibrary;
 import be.nikiroo.fanfix.supported.BasicSupport;
 import be.nikiroo.utils.Progress;
+import be.nikiroo.utils.StringUtils;
 import be.nikiroo.utils.serial.SerialUtils;
 
 /**
@@ -199,6 +207,45 @@ public abstract class BasicReader implements Reader {
                return source;
        }
 
+       /**
+        * Describe a {@link Story} from its {@link MetaData} and return a list of
+        * title/value that represent this {@link Story}.
+        * 
+        * @param meta
+        *            the {@link MetaData} to represent
+        * 
+        * @return the information
+        */
+       public static List<Entry<String, String>> getMetaDesc(MetaData meta) {
+               List<Entry<String, String>> metaDesc = new ArrayList<Entry<String, String>>();
+
+               // TODO: i18n
+
+               StringBuilder tags = new StringBuilder();
+               for (String tag : meta.getTags()) {
+                       if (tags.length() > 0) {
+                               tags.append(", ");
+                       }
+                       tags.append(tag);
+               }
+
+               metaDesc.add(new SimpleEntry<String, String>("Author", meta.getAuthor()));
+               metaDesc.add(new SimpleEntry<String, String>("Publication date",
+                               formatDate(meta.getDate())));
+               metaDesc.add(new SimpleEntry<String, String>("Published on", meta
+                               .getPublisher()));
+               metaDesc.add(new SimpleEntry<String, String>("URL", meta.getUrl()));
+               metaDesc.add(new SimpleEntry<String, String>("Word count", format(meta
+                               .getWords())));
+               metaDesc.add(new SimpleEntry<String, String>("Source", meta.getSource()));
+               metaDesc.add(new SimpleEntry<String, String>("Subject", meta
+                               .getSubject()));
+               metaDesc.add(new SimpleEntry<String, String>("Language", meta.getLang()));
+               metaDesc.add(new SimpleEntry<String, String>("Tags", tags.toString()));
+
+               return metaDesc;
+       }
+
        /**
         * Open the {@link Story} with an external reader (the program will be
         * passed the main file associated with this {@link Story}).
@@ -307,4 +354,44 @@ public abstract class BasicReader implements Reader {
                        }
                }
        }
+
+       static private String format(long value) {
+               String display = "";
+
+               while (value > 0) {
+                       if (!display.isEmpty()) {
+                               display = "." + display;
+                       }
+                       display = (value % 1000) + display;
+                       value = value / 1000;
+               }
+
+               return display;
+       }
+
+       static private String formatDate(String date) {
+               long ms = 0;
+
+               try {
+                       ms = StringUtils.toTime(date);
+               } catch (ParseException e) {
+               }
+
+               if (ms <= 0) {
+                       SimpleDateFormat sdf = new SimpleDateFormat(
+                                       "yyyy-MM-dd'T'HH:mm:ssXXX");
+                       try {
+                               ms = sdf.parse(date).getTime();
+                       } catch (ParseException e) {
+                       }
+               }
+
+               if (ms > 0) {
+                       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                       return sdf.format(new Date(ms));
+               }
+
+               // :(
+               return date;
+       }
 }
index 6ab92347420ddd7ee9d80fa934e8ceed8f88b1b2..59842ad9365378a467bcd4edbcedebd60482dcab 100644 (file)
@@ -1,11 +1,9 @@
 package be.nikiroo.fanfix.reader.tui;
 
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import jexer.TAction;
 import jexer.TButton;
@@ -19,9 +17,9 @@ import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Paragraph;
 import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
 import be.nikiroo.fanfix.data.Story;
+import be.nikiroo.fanfix.reader.BasicReader;
 import be.nikiroo.jexer.TSizeConstraint;
 import be.nikiroo.jexer.TTable;
-import be.nikiroo.utils.StringUtils;
 
 /**
  * This window will contain the {@link Story} in a readable format, with a
@@ -173,69 +171,21 @@ class TuiReaderStoryWindow extends TWindow {
 
                setCurrentTitle(meta.getTitle());
 
-               StringBuilder tags = new StringBuilder();
-               for (String tag : meta.getTags()) {
-                       if (tags.length() > 0) {
-                               tags.append(", ");
-                       }
-                       tags.append(tag);
+               List<Map.Entry<String, String>> metaDesc = BasicReader
+                               .getMetaDesc(meta);
+               String[][] metaDescObj = new String[metaDesc.size()][2];
+               int i = 0;
+               for (Map.Entry<String, String> entry : metaDesc) {
+                       metaDescObj[i][0] = " " + entry.getKey();
+                       metaDescObj[i][1] = entry.getValue();
+                       i++;
                }
 
-               table.setRowData(new String[][] { //
-                               new String[] { " Author", meta.getAuthor() }, //
-                               new String[] { " Publication date", formatDate(meta.getDate()) },
-                               new String[] { " Published on", meta.getPublisher() },
-                               new String[] { " URL", meta.getUrl() },
-                               new String[] { " Word count", format(meta.getWords()) },
-                               new String[] { " Source", meta.getSource() },
-                               new String[] { " Subject", meta.getSubject() },
-                               new String[] { " Language", meta.getLang() },
-                               new String[] { " Tags", tags.toString() } //
-               });
+               table.setRowData(metaDescObj);
                table.setHeaders(Arrays.asList("key", "value"), false);
                table.toTop();
        }
 
-       private String format(long value) {
-               String display = "";
-
-               while (value > 0) {
-                       if (!display.isEmpty()) {
-                               display = "." + display;
-                       }
-                       display = (value % 1000) + display;
-                       value = value / 1000;
-               }
-
-               return display;
-       }
-
-       private String formatDate(String date) {
-               long ms = 0;
-
-               try {
-                       ms = StringUtils.toTime(date);
-               } catch (ParseException e) {
-               }
-
-               if (ms <= 0) {
-                       SimpleDateFormat sdf = new SimpleDateFormat(
-                                       "yyyy-MM-dd'T'HH:mm:ssXXX");
-                       try {
-                               ms = sdf.parse(date).getTime();
-                       } catch (ParseException e) {
-                       }
-               }
-
-               if (ms > 0) {
-                       SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-                       return sdf.format(new Date(ms));
-               }
-
-               // :(
-               return date;
-       }
-
        /**
         * Append the current chapter.
         * 
index dc275950c6297ae561504b18131a1853dfd1a2c5..4683f71507ccaf20b6cbfd76c454640e38368a8e 100644 (file)
@@ -1,36 +1,20 @@
 package be.nikiroo.fanfix.reader.ui;
 
 import java.awt.BorderLayout;
-import java.awt.Color;
 import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.Polygon;
-import java.awt.Rectangle;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.EventListener;
 import java.util.List;
 
-import javax.imageio.ImageIO;
-import javax.swing.ImageIcon;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 
-import be.nikiroo.fanfix.Instance;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.fanfix.reader.Reader;
-import be.nikiroo.utils.Image;
-import be.nikiroo.utils.ui.ImageUtilsAwt;
-import be.nikiroo.utils.ui.UIUtils;
 
 /**
  * A book item presented in a {@link GuiReaderFrame}.
@@ -73,20 +57,8 @@ class GuiReaderBook extends JPanel {
 
        private static final long serialVersionUID = 1L;
 
-       // TODO: export some of the configuration options?
-       private static final int COVER_WIDTH = 100;
-       private static final int COVER_HEIGHT = 150;
-       private static final int SPINE_WIDTH = 5;
-       private static final int SPINE_HEIGHT = 5;
-       private static final int HOFFSET = 20;
-       private static final Color SPINE_COLOR_BOTTOM = new Color(180, 180, 180);
-       private static final Color SPINE_COLOR_RIGHT = new Color(100, 100, 100);
-       private static final int TEXT_WIDTH = COVER_WIDTH + 40;
-       private static final int TEXT_HEIGHT = 50;
        private static final String AUTHOR_COLOR = "#888888";
-       private static final Color BORDER = Color.black;
        private static final long doubleClickDelay = 200; // in ms
-       //
 
        private JLabel icon;
        private JLabel title;
@@ -95,7 +67,6 @@ class GuiReaderBook extends JPanel {
        private Date lastClick;
 
        private List<BookActionListener> listeners;
-       private Reader reader;
        private MetaData meta;
        private boolean cached;
 
@@ -113,7 +84,6 @@ class GuiReaderBook extends JPanel {
         */
        public GuiReaderBook(Reader reader, MetaData meta, boolean cached,
                        boolean seeWordCount) {
-               this.reader = reader;
                this.cached = cached;
                this.meta = meta;
 
@@ -142,15 +112,17 @@ class GuiReaderBook extends JPanel {
                        optSecondary = "";
                }
 
-               icon = new JLabel(generateCoverIcon());
+               icon = new JLabel(GuiReaderCoverImager.generateCoverIcon(
+                               reader.getLibrary(), getMeta()));
                title = new JLabel(
                                String.format(
                                                "<html>"
                                                                + "<body style='width: %d px; height: %d px; text-align: center'>"
                                                                + "%s" + "<br>" + "<span style='color: %s;'>"
                                                                + "%s" + "</span>" + "</body>" + "</html>",
-                                               TEXT_WIDTH, TEXT_HEIGHT, meta.getTitle(), AUTHOR_COLOR,
-                                               optSecondary));
+                                               GuiReaderCoverImager.TEXT_WIDTH,
+                                               GuiReaderCoverImager.TEXT_HEIGHT, meta.getTitle(),
+                                               AUTHOR_COLOR, optSecondary));
 
                setLayout(new BorderLayout(10, 10));
                add(icon, BorderLayout.CENTER);
@@ -181,6 +153,15 @@ class GuiReaderBook extends JPanel {
                }
        }
 
+       /**
+        * The item mouse-hover state.
+        * 
+        * @return TRUE if it is mouse-hovered
+        */
+       private boolean isHovered() {
+               return this.hovered;
+       }
+
        /**
         * The item mouse-hover state.
         * 
@@ -306,172 +287,7 @@ class GuiReaderBook extends JPanel {
        @Override
        public void paint(Graphics g) {
                super.paint(g);
-               paintOverlay(g);
-       }
-
-       /**
-        * Draw a partially transparent overlay if needed depending upon the
-        * selection and mouse-hover states on top of the normal component, as well
-        * as a possible "cached" icon if the item is cached.
-        * 
-        * @param g
-        *            the {@link Graphics} to paint onto
-        */
-       public void paintOverlay(Graphics g) {
-               Rectangle clip = g.getClipBounds();
-               if (clip.getWidth() <= 0 || clip.getHeight() <= 0) {
-                       return;
-               }
-
-               int h = COVER_HEIGHT;
-               int w = COVER_WIDTH;
-               int xOffset = (TEXT_WIDTH - COVER_WIDTH) - 1;
-               int yOffset = HOFFSET;
-
-               if (BORDER != null) {
-                       if (BORDER != null) {
-                               g.setColor(BORDER);
-                               g.drawRect(xOffset, yOffset, COVER_WIDTH, COVER_HEIGHT);
-                       }
-
-                       xOffset++;
-                       yOffset++;
-               }
-
-               int[] xs = new int[] { xOffset, xOffset + SPINE_WIDTH,
-                               xOffset + w + SPINE_WIDTH, xOffset + w };
-               int[] ys = new int[] { yOffset + h, yOffset + h + SPINE_HEIGHT,
-                               yOffset + h + SPINE_HEIGHT, yOffset + h };
-               g.setColor(SPINE_COLOR_BOTTOM);
-               g.fillPolygon(new Polygon(xs, ys, xs.length));
-               xs = new int[] { xOffset + w, xOffset + w + SPINE_WIDTH,
-                               xOffset + w + SPINE_WIDTH, xOffset + w };
-               ys = new int[] { yOffset, yOffset + SPINE_HEIGHT,
-                               yOffset + h + SPINE_HEIGHT, yOffset + h };
-               g.setColor(SPINE_COLOR_RIGHT);
-               g.fillPolygon(new Polygon(xs, ys, xs.length));
-
-               Color color = new Color(255, 255, 255, 0);
-               if (!isEnabled()) {
-               } else if (selected && !hovered) {
-                       color = new Color(80, 80, 100, 40);
-               } else if (!selected && hovered) {
-                       color = new Color(230, 230, 255, 100);
-               } else if (selected && hovered) {
-                       color = new Color(200, 200, 255, 100);
-               }
-
-               g.setColor(color);
-               g.fillRect(clip.x, clip.y, clip.width, clip.height);
-
-               if (cached) {
-                       UIUtils.drawEllipse3D(g, Color.green.darker(), COVER_WIDTH
-                                       + HOFFSET + 30, 10, 20, 20);
-               }
-       }
-
-       /**
-        * Generate a cover icon based upon the given {@link MetaData}.
-        * 
-        * @return the icon
-        */
-       private ImageIcon generateCoverIcon() {
-               BufferedImage resizedImage = null;
-               String id = getIconId(meta);
-
-               InputStream in = Instance.getCache().getFromCache(id);
-               if (in != null) {
-                       try {
-                               resizedImage = ImageUtilsAwt.fromImage(new Image(in));
-                               in.close();
-                               in = null;
-                       } catch (IOException e) {
-                               Instance.getTraceHandler().error(e);
-                       }
-               }
-
-               if (resizedImage == null) {
-                       try {
-                               Image cover = null;
-                               if (meta.getLuid() != null) {
-                                       cover = reader.getLibrary().getCover(meta.getLuid());
-                               }
-                               if (cover == null) {
-                                       cover = reader.getLibrary()
-                                                       .getSourceCover(meta.getSource());
-                               }
-
-                               resizedImage = new BufferedImage(SPINE_WIDTH + COVER_WIDTH,
-                                               SPINE_HEIGHT + COVER_HEIGHT + HOFFSET,
-                                               BufferedImage.TYPE_4BYTE_ABGR);
-                               Graphics2D g = resizedImage.createGraphics();
-                               g.setColor(Color.white);
-                               g.fillRect(0, HOFFSET, COVER_WIDTH, COVER_HEIGHT);
-                               if (cover != null) {
-                                       BufferedImage coverb = ImageUtilsAwt.fromImage(cover);
-                                       g.drawImage(coverb, 0, HOFFSET, COVER_WIDTH, COVER_HEIGHT,
-                                                       null);
-                               } else {
-                                       g.setColor(Color.black);
-                                       g.drawLine(0, HOFFSET, COVER_WIDTH, HOFFSET + COVER_HEIGHT);
-                                       g.drawLine(COVER_WIDTH, HOFFSET, 0, HOFFSET + COVER_HEIGHT);
-                               }
-                               g.dispose();
-
-                               if (id != null) {
-                                       ByteArrayOutputStream out = new ByteArrayOutputStream();
-                                       ImageIO.write(resizedImage, "png", out);
-                                       byte[] imageBytes = out.toByteArray();
-                                       in = new ByteArrayInputStream(imageBytes);
-                                       Instance.getCache().addToCache(in, id);
-                                       in.close();
-                                       in = null;
-                               }
-                       } catch (MalformedURLException e) {
-                               Instance.getTraceHandler().error(e);
-                       } catch (IOException e) {
-                               Instance.getTraceHandler().error(e);
-                       }
-               }
-
-               if (resizedImage != null) {
-                       return new ImageIcon(resizedImage);
-               }
-
-               return null;
-       }
-
-       /**
-        * Manually clear the icon set for this item.
-        * 
-        * @param meta
-        *            the meta of the story or source (if luid is null)
-        */
-       public static void clearIcon(MetaData meta) {
-               String id = getIconId(meta);
-               Instance.getCache().removeFromCache(id);
-       }
-
-       /**
-        * Get a unique ID from this meta (note that if the luid is null, it is
-        * considered a source and not a {@link Story}).
-        * 
-        * @param meta
-        *            the meta
-        * @return the unique ID
-        */
-       private static String getIconId(MetaData meta) {
-               String id = null;
-
-               String key = meta.getUuid();
-               if (meta.getLuid() == null) {
-                       // a fake meta (== a source)
-                       key = "source_" + meta.getSource();
-               }
-
-               id = key + ".thumb_" + SPINE_WIDTH + "x" + COVER_WIDTH + "+"
-                               + SPINE_HEIGHT + "+" + COVER_HEIGHT + "@" + HOFFSET;
-
-               return id;
+               GuiReaderCoverImager.paintOverlay(g, isEnabled(), isSelected(),
+                               isHovered(), isCached());
        }
 }
index b8db8f747e420de4e89884aeb47be5a71105d10c..8d3142c315679465525ae17efd9ea3b92e46f6f0 100644 (file)
@@ -2,6 +2,7 @@ package be.nikiroo.fanfix.reader.ui;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Font;
 import java.awt.Frame;
 import java.awt.Toolkit;
 import java.awt.datatransfer.DataFlavor;
@@ -20,7 +21,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
+import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
@@ -31,6 +34,7 @@ import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
 import javax.swing.filechooser.FileFilter;
@@ -308,6 +312,8 @@ class GuiReaderFrame extends JFrame {
                                popup.add(createMenuItemRedownload());
                                popup.addSeparator();
                                popup.add(createMenuItemDelete());
+                               popup.addSeparator();
+                               popup.add(createMenuItemProperties());
                                popup.show(e.getComponent(), e.getX(), e.getY());
                        }
 
@@ -653,7 +659,8 @@ class GuiReaderFrame extends JFrame {
                                                        reader.clearLocalReaderCache(selectedBook.getMeta()
                                                                        .getLuid());
                                                        selectedBook.setCached(false);
-                                                       GuiReaderBook.clearIcon(selectedBook.getMeta());
+                                                       GuiReaderCoverImager.clearIcon(selectedBook
+                                                                       .getMeta());
                                                        SwingUtilities.invokeLater(new Runnable() {
                                                                @Override
                                                                public void run() {
@@ -796,6 +803,110 @@ class GuiReaderFrame extends JFrame {
                return delete;
        }
 
+       /**
+        * Create the properties menu item.
+        * 
+        * @return the item
+        */
+       private JMenuItem createMenuItemProperties() {
+               JMenuItem delete = new JMenuItem("Properties", KeyEvent.VK_P);
+               delete.addActionListener(new ActionListener() {
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (selectedBook != null) {
+                                       outOfUi(null, new Runnable() {
+                                               @Override
+                                               public void run() {
+                                                       final MetaData meta = selectedBook.getMeta();
+                                                       new JFrame() {
+                                                               private static final long serialVersionUID = 1L;
+                                                               @SuppressWarnings("unused")
+                                                               private Object init = init();
+
+                                                               private Object init() {
+                                                                       // Borders
+                                                                       int top = 20;
+                                                                       int space = 10;
+
+                                                                       // Image
+                                                                       ImageIcon img = GuiReaderCoverImager
+                                                                                       .generateCoverIcon(
+                                                                                                       reader.getLibrary(), meta);
+
+                                                                       // frame
+                                                                       setTitle(meta.getLuid() + ": "
+                                                                                       + meta.getTitle());
+
+                                                                       setSize(800, img.getIconHeight() + 2 * top);
+                                                                       setLayout(new BorderLayout());
+
+                                                                       // Main panel
+                                                                       JPanel mainPanel = new JPanel(
+                                                                                       new BorderLayout());
+                                                                       JPanel mainPanelKeys = new JPanel();
+                                                                       mainPanelKeys.setLayout(new BoxLayout(
+                                                                                       mainPanelKeys, BoxLayout.Y_AXIS));
+                                                                       JPanel mainPanelValues = new JPanel();
+                                                                       mainPanelValues.setLayout(new BoxLayout(
+                                                                                       mainPanelValues, BoxLayout.Y_AXIS));
+
+                                                                       mainPanel.add(mainPanelKeys,
+                                                                                       BorderLayout.WEST);
+                                                                       mainPanel.add(mainPanelValues,
+                                                                                       BorderLayout.CENTER);
+
+                                                                       List<Entry<String, String>> infos = BasicReader
+                                                                                       .getMetaDesc(meta);
+
+                                                                       Color trans = new Color(0, 0, 0, 1);
+                                                                       for (Entry<String, String> info : infos) {
+                                                                               JTextArea key = new JTextArea(info
+                                                                                               .getKey());
+                                                                               key.setFont(new Font(key.getFont()
+                                                                                               .getFontName(), Font.BOLD, key
+                                                                                               .getFont().getSize()));
+                                                                               key.setEditable(false);
+                                                                               key.setLineWrap(false);
+                                                                               key.setBackground(trans);
+                                                                               mainPanelKeys.add(key);
+
+                                                                               JTextArea value = new JTextArea(info
+                                                                                               .getValue());
+                                                                               value.setEditable(false);
+                                                                               value.setLineWrap(false);
+                                                                               value.setBackground(trans);
+                                                                               mainPanelValues.add(value);
+                                                                       }
+
+                                                                       // Image
+                                                                       JLabel imgLabel = new JLabel(img);
+                                                                       imgLabel.setVerticalAlignment(JLabel.TOP);
+
+                                                                       // Borders
+                                                                       mainPanelKeys.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(top, space, 0, 0));
+                                                                       mainPanelValues.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(top, space, 0, 0));
+                                                                       imgLabel.setBorder(BorderFactory
+                                                                                       .createEmptyBorder(0, space, 0, 0));
+
+                                                                       // Add all
+                                                                       add(imgLabel, BorderLayout.WEST);
+                                                                       add(mainPanel, BorderLayout.CENTER);
+
+                                                                       return null;
+                                                               }
+
+                                                       }.setVisible(true);
+                                               }
+                                       });
+                               }
+                       }
+               });
+
+               return delete;
+       }
+
        /**
         * Create the open menu item for a book or a source (no LUID).
         * 
@@ -838,7 +949,7 @@ class GuiReaderFrame extends JFrame {
                                                        selectedBook.getMeta().getLuid());
                                        MetaData source = selectedBook.getMeta().clone();
                                        source.setLuid(null);
-                                       GuiReaderBook.clearIcon(source);
+                                       GuiReaderCoverImager.clearIcon(source);
                                }
                        }
                });