In this mode, you can:
- Import a story from its URL (or even another file)
- Export a story to a file (.epub or .cbz)
-- Display a story from the local library
+- Display a story from the local library in text format in the console
+- Display a story from the local library graphically **by calling a native program to handle it** (though Fanfix can automatically process it into HTML so any browser can open it)
## Supported websites
## TODO
Currently missing, but either in progress or planned:
-- A GUI (work in progress)
-- Some readers other than CLI (TUI, GUI)
-- Check if it can work on Android
-- French translation
+- [ ] A GUI (work in progress)
+ - [x] Make one
+ - [x] Make it run when no args passed
+ - [ ] Fix the UI, it is ugly
+ - [ ] Work on the UI thread is BAD
+ - [ ] Allow export
+ - [ ] Show a list of types
+ - [x] ..in the menu
+ - [ ] ..as a screen view
+ - options screen
+- [ ] A TUI reader
+- [ ] Check if it can work on Android
+- [ ] Translations
+ - [x] i18n system in place
+ - [x] Make use of it
+ - [x] Use it for all user output (some WIP remains)
+ - [ ] French translation
+- [ ] Allow lauching a custom application instead of Desktop.star ?
+ - [ ] Make a wrapper for firefox to create a new, empty profile ?
+
dir.mkdirs();
}
+ /**
+ * List all the known types of stories.
+ *
+ * @return the types
+ */
+ public List<String> getTypes() {
+ List<String> list = new ArrayList<String>();
+ for (Entry<MetaData, File> entry : getStories().entrySet()) {
+ String storyType = entry.getValue().getParentFile().getName();
+ if (!list.contains(storyType)) {
+ list.add(storyType);
+ }
+ }
+
+ return list;
+ }
+
/**
* List all the stories of the given source type in the {@link Library}, or
* all the stories if NULL is passed as a type.
*
* @return the stories
*/
- public List<MetaData> getList(SupportType type) {
- String typeString = type == null ? null : type.getSourceName();
-
+ public List<MetaData> getList(String type) {
List<MetaData> list = new ArrayList<MetaData>();
for (Entry<MetaData, File> entry : getStories().entrySet()) {
String storyType = entry.getValue().getParentFile().getName();
- if (typeString == null || typeString.equalsIgnoreCase(storyType)) {
+ if (type == null || type.equalsIgnoreCase(storyType)) {
list.add(entry.getKey());
}
}
*/
public class Main {
private enum MainAction {
- IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER
+ IMPORT, EXPORT, CONVERT, READ, READ_URL, LIST, HELP, SET_READER, START,
}
/**
* target</li>
* <li>--read [id] ([chapter number]): read the given story from the library
* </li>
- * <li>--read-url [URL] ([cahpter number]): convert on the fly and read the
+ * <li>--read-url [URL] ([chapter number]): convert on the fly and read the
* story, without saving it</li>
- * <li>--list: list the stories present in the library</li>
+ * <li>--list ([type]): list the stories present in the library</li>
* <li>--set-reader [reader type]: set the reader type to CLI or LOCAL for
* this command</li>
* </ul>
String typeString = null;
String chapString = null;
String target = null;
- MainAction action = MainAction.HELP;
+ MainAction action = MainAction.START;
Boolean plusInfo = null;
boolean noMoreActions = false;
case SET_READER:
exitCode = setReaderType(args[i]);
break;
+ case START:
+ exitCode = 255; // not supposed to be selected by user
+ break;
}
}
break;
case SET_READER:
break;
+ case START:
+ BasicReader.setDefaultReaderType(ReaderType.LOCAL);
+ BasicReader.getReader().start(null);
+ break;
}
}
*
* @return the exit return code (0 = success)
*/
- private static int imprt(String urlString) {
+ public static int imprt(String urlString) {
try {
Story story = Instance.getLibrary().imprt(getUrl(urlString));
System.out.println(story.getMeta().getLuid() + ": \""
*
* @return the exit return code (0 = success)
*/
- private static int export(String luid, String typeString, String target) {
+ public static int export(String luid, String typeString, String target) {
OutputType type = OutputType.valueOfNullOkUC(typeString);
if (type == null) {
Instance.syserr(new Exception(trans(StringId.OUTPUT_DESC,
* is passed, in which case all stories will be listed).
*
* @param typeString
- * the {@link SupportType} to list the known stories of, or NULL
- * to list all stories
+ * the type to list the known stories of, or NULL to list all
+ * stories
*
* @return the exit return code (0 = success)
*/
- private static int list(String typeString) {
- SupportType type = null;
- try {
- type = SupportType.valueOfNullOkUC(typeString);
- } catch (Exception e) {
- Instance.syserr(new Exception(
- trans(StringId.INPUT_DESC, typeString), e));
- return 1;
- }
-
+ private static int list(String type) {
BasicReader.getReader().start(type);
-
return 0;
}
} else {
try {
BasicSupport support = BasicSupport.getSupport(source);
-
+
if (support != null) {
Story story = support.process(source);
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
import be.nikiroo.fanfix.Instance;
-import be.nikiroo.fanfix.bundles.StringId;
+import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix.data.Chapter;
+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.utils.IOUtils;
import be.nikiroo.utils.StringUtils;
class Html extends BasicOutput {
+ private File dir;
protected FileWriter writer;
private boolean inDialogue = false;
private boolean inNormal = false;
@Override
public File process(Story story, File targetDir, String targetName)
throws IOException {
+ String targetNameOrig = targetName;
+
File target = new File(targetDir, targetName);
target.mkdir();
+ dir = target;
targetName = new File(targetName, "index").getPath();
-
- String targetNameOrig = targetName;
targetName += getDefaultExtension();
target = new File(targetDir, targetName);
writer = null;
}
+ String format = Instance.getConfig()
+ .getString(Config.IMAGE_FORMAT_COVER).toLowerCase();
+ if (story.getMeta().getCover() != null) {
+ ImageIO.write(story.getMeta().getCover(), format, new File(dir,
+ "cover." + format));
+ }
+
return target;
}
@Override
protected void writeStoryHeader(Story story) throws IOException {
String title = "";
+ String tags = "";
+ String author = "";
+ Chapter resume = null;
if (story.getMeta() != null) {
- title = story.getMeta().getTitle();
+ MetaData meta = story.getMeta();
+ title = meta.getTitle();
+ resume = meta.getResume();
+ if (meta.getTags() != null) {
+ for (String tag : meta.getTags()) {
+ if (!tags.isEmpty()) {
+ tags += ", ";
+ }
+ tags += tag;
+ }
+
+ if (!tags.isEmpty()) {
+ tags = "(" + tags + ")";
+ }
+ }
+ author = meta.getAuthor();
+ }
+
+ String format = Instance.getConfig()
+ .getString(Config.IMAGE_FORMAT_COVER).toLowerCase();
+
+ InputStream inStyle = getClass().getResourceAsStream("html.style.css");
+ if (inStyle == null) {
+ throw new IOException("Cannot find style.css resource");
+ }
+ try {
+ IOUtils.write(inStyle, new File(dir, "style.css"));
+ } finally {
+ inStyle.close();
}
writer.write("<!DOCTYPE html>");
writer.write("\n<head>");
writer.write("\n <meta http-equiv='content-type' content='text/html; charset=utf-8'>");
writer.write("\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>");
+ writer.write("\n <link rel='stylesheet' type='text/css' href='style.css'>");
writer.write("\n <title>" + StringUtils.xmlEscape(title) + "</title>");
writer.write("\n</head>");
writer.write("\n<body>\n");
- writer.write("<h1>" + StringUtils.xmlEscape(title) + "</h1>\n\n");
+ writer.write("\n <div class=\"titlepage\">");
+ writer.write("\n <h1>" + StringUtils.xmlEscape(title) + "</h1>");
+ writer.write("\n <div class=\"type\">" + StringUtils.xmlEscape(tags)
+ + "</div>");
+ writer.write("\n <div class=\"cover\">");
+ writer.write("\n <img src=\"cover." + format + "\"></img>");
+ writer.write("\n </div>");
+ writer.write("\n <div class=\"author\">"
+ + StringUtils.xmlEscape(author) + "</div>");
+ writer.write("\n </div>");
+
+ writer.write("\n <hr/><br/>");
+
+ if (resume != null) {
+ for (Paragraph para : resume) {
+ writeParagraph(para);
+ }
+ if (inDialogue) {
+ writer.write(" </div>\n");
+ inDialogue = false;
+ }
+ if (inNormal) {
+ writer.write(" </div>\n");
+ inNormal = false;
+ }
+ }
+
+ writer.write("\n <br/>");
}
@Override
@Override
protected void writeChapterHeader(Chapter chap) throws IOException {
- String txt;
+ String nameOrNumber;
if (chap.getName() != null && !chap.getName().isEmpty()) {
- txt = Instance.getTrans().getString(StringId.CHAPTER_NAMED,
- chap.getNumber(), chap.getName());
+ nameOrNumber = chap.getName();
} else {
- txt = Instance.getTrans().getString(StringId.CHAPTER_UNNAMED,
- chap.getNumber());
+ nameOrNumber = Integer.toString(chap.getNumber());
}
- writer.write("<h1>" + StringUtils.xmlEscape(txt) + "</h1>\n\n");
+ writer.write("\n <h2>");
+ writer.write("\n <span class='chap'>Chapter <span class='chapnumber'>"
+ + chap.getNumber() + "</span>:</span> ");
+ writer.write("\n <span class='chaptitle'>"
+ + StringUtils.xmlEscape(nameOrNumber) + "</span>");
+ writer.write("\n </h2>");
+ writer.write("\n ");
+ writer.write("\n <div class='chapter_content'>\n");
inDialogue = false;
inNormal = false;
}
+ @Override
+ protected void writeChapterFooter(Chapter chap) throws IOException {
+ if (inDialogue) {
+ writer.write(" </div>\n");
+ inDialogue = false;
+ }
+ if (inNormal) {
+ writer.write(" </div>\n");
+ inNormal = false;
+ }
+
+ writer.write("\n </div>");
+ }
+
@Override
protected void writeParagraphHeader(Paragraph para) throws IOException {
if (para.getType() == ParagraphType.QUOTE && !inDialogue) {
--- /dev/null
+html {
+ text-align: justify;
+ max-width: 800px;
+ margin: auto;
+}
+
+.titlepage {
+ padding-left: 10%;
+ padding-right: 10%;
+ width: 80%;
+}
+
+h1 {
+ padding-bottom: 0;
+ margin-bottom: 0;
+ text-align: left;
+}
+
+.type {
+ position: relative;
+ font-size: large;
+ color: #666666;
+ font-weight: bold;
+ padding-bottom: 10px;
+ text-align: left;
+}
+
+.cover, .page-image {
+ width: 100%;
+}
+
+.cover img {
+ height: 45%;
+ max-width: 100%;
+ margin: auto;
+}
+
+.author {
+ text-align: right;
+ font-size: large;
+ font-style: italic;
+}
+
+.book, .chapter_content {
+ text-indent: 40px;
+ padding-top: 40px;
+ padding-left: 5%;
+ padding-right: 5%;
+ width: 90%;
+}
+
+h2 {
+ border: 1px solid black;
+ color: #222222;
+ padding-left: 10px;
+ padding-right: 10px;
+ display: block;
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+
+h2 .chap {
+ color: #000000;
+ font-size: large;
+ font-variant: small-caps;
+ display: block;
+}
+
+h2 .chap:first-letter {
+ font-weight: bold;
+}
+
+h2 .chapnumber {
+ color: #000000;
+ font-size: xx-large;
+}
+
+h2 .chaptitle {
+ color: #444444;
+ font-size: large;
+ font-style: italic;
+ padding-bottom: 5px;
+ text-align: right;
+ display: block;
+}
+
+.normals {
+ /* padding-bottom: 20px; */
+
+}
+
+.normal {
+ /* padding-bottom: 20px; */
+
+}
+
+.dialogues {
+ /* padding-top: 10px;
+ padding-bottom: 10px; */
+
+}
+
+.dialogue {
+ font-style: italic;
+}
\ No newline at end of file
import be.nikiroo.fanfix.bundles.Config;
import be.nikiroo.fanfix.data.Story;
import be.nikiroo.fanfix.supported.BasicSupport;
-import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
/**
* The class that handles the different {@link Story} readers you can use.
* the type of {@link Story} to take into account, or NULL for
* all
*/
- public abstract void start(SupportType type);
+ public abstract void start(String type);
/**
* Return a new {@link BasicReader} ready for use if one is configured.
* @return a {@link BasicReader}, or NULL if none configured
*/
public static BasicReader getReader() {
- if (defaultType != null) {
- switch (defaultType) {
- // case LOCAL:
- // return new LocalReader().setType(ReaderType.LOCAL);
- case CLI:
- return new CliReader().setType(ReaderType.CLI);
+ try {
+ if (defaultType != null) {
+ switch (defaultType) {
+ case LOCAL:
+ return new LocalReader().setType(ReaderType.LOCAL);
+ case CLI:
+ return new CliReader().setType(ReaderType.CLI);
+ }
}
+ } catch (IOException e) {
+ Instance.syserr(new Exception("Cannot create a reader of type: "
+ + defaultType, e));
}
return null;
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Paragraph;
import be.nikiroo.fanfix.data.Story;
-import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
/**
* Command line {@link Story} reader.
}
@Override
- public void start(SupportType type) {
+ public void start(String type) {
List<MetaData> stories;
stories = Instance.getLibrary().getList(type);
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Story;
import be.nikiroo.fanfix.output.BasicOutput.OutputType;
-import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
class LocalReader extends BasicReader {
private Library lib;
}
@Override
- public void start(SupportType type) {
- final SupportType typeFinal = type;
+ public void start(String type) {
+ final String typeFinal = type;
EventQueue.invokeLater(new Runnable() {
public void run() {
new LocalReaderFrame(LocalReader.this, typeFinal)
}
});
}
-
- public static void main(String[] args) throws IOException {
- new LocalReader().start(null);
- }
}
--- /dev/null
+package be.nikiroo.fanfix.reader;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EventListener;
+import java.util.List;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import be.nikiroo.fanfix.data.MetaData;
+
+/**
+ * A book item presented in a {@link LocalReaderFrame}.
+ *
+ * @author niki
+ */
+class LocalReaderBook extends JPanel {
+ /**
+ * Action on a book item.
+ *
+ * @author niki
+ */
+ interface BookActionListner extends EventListener {
+ /**
+ * The book was selected (single click).
+ *
+ * @param book
+ * the {@link LocalReaderBook} itself
+ */
+ public void select(LocalReaderBook book);
+
+ /**
+ * The book was double-clicked.
+ *
+ * @param book
+ * the {@link LocalReaderBook} itself
+ */
+ public void action(LocalReaderBook book);
+ }
+
+ private static final long serialVersionUID = 1L;
+ private JLabel icon;
+ private JLabel title;
+ private JLabel author;
+ private boolean selected;
+ private boolean hovered;
+ private Date lastClick;
+ private long doubleClickDelay = 200; // in ms
+ private List<BookActionListner> listeners;
+
+ public LocalReaderBook(MetaData meta) {
+ if (meta.getCover() != null) {
+ BufferedImage resizedImage = new BufferedImage(100, 150,
+ BufferedImage.TYPE_4BYTE_ABGR);
+ Graphics2D g = resizedImage.createGraphics();
+ g.drawImage(meta.getCover(), 0, 0, 100, 150, null);
+ g.dispose();
+
+ icon = new JLabel(new ImageIcon(resizedImage));
+ } else {
+ icon = new JLabel(" [ no cover ] ");
+ }
+
+ title = new JLabel(meta.getTitle());
+ author = new JLabel("by " + meta.getAuthor());
+
+ this.setLayout(new BorderLayout());
+ this.add(icon, BorderLayout.CENTER);
+ this.add(title, BorderLayout.SOUTH);
+
+ setupListeners();
+ setSelected(false);
+ }
+
+ /**
+ * The book current selection state.
+ *
+ * @return the selected
+ */
+ public boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * The book current selection state.
+ *
+ * @param selected
+ * the selected to set
+ */
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ fixColor();
+ }
+
+ private void setHovered(boolean hovered) {
+ this.hovered = hovered;
+ fixColor();
+ }
+
+ private void fixColor() {
+ if (selected && !hovered) {
+ setBackground(new Color(180, 180, 255));
+ } else if (!selected && hovered) {
+ setBackground(new Color(230, 230, 255));
+ } else if (selected && hovered) {
+ setBackground(new Color(200, 200, 255));
+ } else {
+ setBackground(new Color(255, 255, 255));
+ }
+ }
+
+ private void setupListeners() {
+ listeners = new ArrayList<LocalReaderBook.BookActionListner>();
+ addMouseListener(new MouseListener() {
+ public void mouseReleased(MouseEvent e) {
+ }
+
+ public void mousePressed(MouseEvent e) {
+ }
+
+ public void mouseExited(MouseEvent e) {
+ setHovered(false);
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ setHovered(true);
+ }
+
+ public void mouseClicked(MouseEvent e) {
+ Date now = new Date();
+ if (lastClick != null
+ && now.getTime() - lastClick.getTime() < doubleClickDelay) {
+ click(true);
+ } else {
+ click(false);
+ }
+ lastClick = now;
+ }
+ });
+ }
+
+ private void click(boolean doubleClick) {
+ for (BookActionListner listener : listeners) {
+ if (doubleClick) {
+ listener.action(this);
+ } else {
+ listener.select(this);
+ }
+ }
+ }
+
+ public void addActionListener(BookActionListner listener) {
+ listeners.add(listener);
+ }
+}
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowEvent;
+import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
-import javax.swing.JButton;
import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.Main;
import be.nikiroo.fanfix.data.MetaData;
-import be.nikiroo.fanfix.supported.BasicSupport.SupportType;
+import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListner;
class LocalReaderFrame extends JFrame {
private static final long serialVersionUID = 1L;
private LocalReader reader;
+ private List<MetaData> stories;
+ private List<LocalReaderBook> books;
+ private JPanel bookPane;
+ private String type;
- public LocalReaderFrame(LocalReader reader, SupportType type) {
+ public LocalReaderFrame(LocalReader reader, String type) {
super("HTML reader");
this.reader = reader;
setSize(800, 600);
setLayout(new FlowLayout());
- // TODO: list all stories, list all TMP stories (and format?)
+ books = new ArrayList<LocalReaderBook>();
+ bookPane = new JPanel();
+ add(bookPane);
- List<MetaData> stories = Instance.getLibrary().getList(type);
- for (MetaData story : stories) {
- JButton button = new JButton(story.getTitle());
- final String luid = story.getLuid();
- button.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
+ refreshBooks(type);
+ setJMenuBar(createMenu());
+
+ setVisible(true);
+ }
+
+ private void refreshBooks(String type) {
+ this.type = type;
+ stories = Instance.getLibrary().getList(type);
+ books.clear();
+ bookPane.removeAll();
+ for (MetaData meta : stories) {
+ LocalReaderBook book = new LocalReaderBook(meta);
+ books.add(book);
+ final String luid = meta.getLuid();
+ book.addActionListener(new BookActionListner() {
+ public void select(LocalReaderBook book) {
+ for (LocalReaderBook abook : books) {
+ abook.setSelected(abook == book);
+ }
+ }
+
+ public void action(LocalReaderBook book) {
try {
- // TODO: config option (image, non image): TXT,
- // custom-HTML, CBZ, EPUB
- Desktop.getDesktop().browse(
- LocalReaderFrame.this.reader.getTarget(luid)
- .toURI());
- } catch (IOException e1) {
- e1.printStackTrace();
+ File target = LocalReaderFrame.this.reader
+ .getTarget(luid);
+ Desktop.getDesktop().browse(target.toURI());
+ } catch (IOException e) {
+ Instance.syserr(e);
}
}
});
- add(button);
+ bookPane.add(book);
}
- setVisible(true);
+ bookPane.validate();
+ bookPane.repaint();
+ }
+
+ private JMenuBar createMenu() {
+ JMenuBar bar = new JMenuBar();
+
+ JMenu file = new JMenu("File");
+
+ JMenuItem imprt = new JMenuItem("Import", KeyEvent.VK_I);
+ imprt.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String url = JOptionPane.showInputDialog(LocalReaderFrame.this,
+ "url?");
+ if (Main.imprt(url) != 0) {
+ JOptionPane.showMessageDialog(LocalReaderFrame.this,
+ "Cannot import", "Imort error",
+ JOptionPane.ERROR_MESSAGE);
+ } else {
+ refreshBooks(type);
+ }
+ }
+ });
+ JMenu types = new JMenu("Type");
+ List<String> tt = Instance.getLibrary().getTypes();
+ tt.add(0, null);
+ for (final String type : tt) {
+ JMenuItem item = new JMenuItem(type == null ? "[all]" : type);
+ item.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ refreshBooks(type);
+ }
+ });
+ types.add(item);
+ }
+ JMenuItem exit = new JMenuItem("Exit", KeyEvent.VK_X);
+ exit.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ LocalReaderFrame.this.dispatchEvent(new WindowEvent(
+ LocalReaderFrame.this, WindowEvent.WINDOW_CLOSING));
+ }
+ });
+
+ file.add(imprt);
+ file.add(types);
+ file.addSeparator();
+ file.add(exit);
+
+ bar.add(file);
+
+ return bar;
}
}
String line = scan.next().trim();
boolean image = false;
if (line.startsWith("[") && line.endsWith("]")) {
- URL url = getImageUrl(source,
+ URL url = getImageUrl(this, source,
line.substring(1, line.length() - 1).trim());
if (url != null) {
paras.add(new Paragraph(url));
&& Instance.getCoverDir() != null) {
try {
File fileCover = new File(Instance.getCoverDir(), subject);
- return getImage(fileCover.toURI().toURL(), subject);
+ return getImage(null, fileCover.toURI().toURL(), subject);
} catch (MalformedURLException e) {
}
}
}
}
- static BufferedImage getImage(URL source, String line) {
- URL url = getImageUrl(source, line);
+ static BufferedImage getImage(BasicSupport support, URL source, String line) {
+ URL url = getImageUrl(support, source, line);
if (url != null) {
InputStream in = null;
try {
* @return the image URL if found, or NULL
*
*/
- static URL getImageUrl(URL source, String line) {
+ static URL getImageUrl(BasicSupport support, URL source, String line) {
URL url = null;
if (line != null) {
if (source != null) {
path = new File(source.getFile()).getParent();
try {
- String urlBase = new File(new File(path), line.trim())
- .toURI().toURL().toString();
+ String basePath = new File(new File(path), line.trim())
+ .getAbsolutePath();
for (String ext : getImageExt(true)) {
- if (new File(urlBase + ext).exists()) {
- url = new File(urlBase + ext).toURI().toURL();
+ if (new File(basePath + ext).exists()) {
+ url = new File(basePath + ext).toURI().toURL();
}
}
} catch (Exception e) {
for (String ext : getImageExt(true)) {
if (Instance.getCache().check(new URL(line + ext))) {
url = new URL(line + ext);
+ break;
}
}
for (String ext : getImageExt(true)) {
try {
url = new URL(line + ext);
- Instance.getCache().refresh(url,
- getSupport(url), true);
+ Instance.getCache().refresh(url, support, true);
break;
} catch (IOException e) {
// no image with this ext
// refresh the cached file
if (url != null) {
try {
- Instance.getCache().refresh(url, getSupport(url), true);
+ Instance.getCache().refresh(url, support, true);
} catch (IOException e) {
// woops, broken image
url = null;
+ "/" + url.getPath() + "/" + line;
}
- return getImage(null, line);
+ return getImage(this, null, line);
}
}
}
String line = getLine(in, "id=chap_select", 0);
String key = "<option value=";
int i = 1;
- for (pos = line.indexOf(key); pos >= 0; pos = line.indexOf(key, pos), i++) {
- pos = line.indexOf('>', pos);
- if (pos >= 0) {
- int endOfName = line.indexOf('<', pos);
- if (endOfName >= 0) {
- String name = line.substring(pos + 1, endOfName);
- String chapNum = i + ".";
- if (name.startsWith(chapNum)) {
- name = name.substring(chapNum.length(), name.length());
- }
- try {
- final String chapName = name.trim();
- final URL chapURL = new URL(base + i + suffix);
- urls.add(new Entry<String, URL>() {
- public URL setValue(URL value) {
- return null;
- }
-
- public URL getValue() {
- return chapURL;
- }
-
- public String getKey() {
- return chapName;
- }
- });
- } catch (MalformedURLException e) {
- Instance.syserr(new IOException("Cannot parse chapter "
- + i + " url: " + (base + i + suffix), e));
+ if (line != null) {
+ for (pos = line.indexOf(key); pos >= 0; pos = line
+ .indexOf(key, pos), i++) {
+ pos = line.indexOf('>', pos);
+ if (pos >= 0) {
+ int endOfName = line.indexOf('<', pos);
+ if (endOfName >= 0) {
+ String name = line.substring(pos + 1, endOfName);
+ String chapNum = i + ".";
+ if (name.startsWith(chapNum)) {
+ name = name.substring(chapNum.length(),
+ name.length());
+ }
+
+ try {
+ final String chapName = name.trim();
+ final URL chapURL = new URL(base + i + suffix);
+ urls.add(new Entry<String, URL>() {
+ public URL setValue(URL value) {
+ return null;
+ }
+
+ public URL getValue() {
+ return chapURL;
+ }
+
+ public String getKey() {
+ return chapName;
+ }
+ });
+ } catch (MalformedURLException e) {
+ Instance.syserr(new IOException(
+ "Cannot parse chapter " + i + " url: "
+ + (base + i + suffix), e));
+ }
}
}
}
+ } else {
+ // only one chapter:
+ final String chapName = getTitle(reset(in));
+ final URL chapURL = source;
+ urls.add(new Entry<String, URL>() {
+ public URL setValue(URL value) {
+ return null;
+ }
+
+ public URL getValue() {
+ return chapURL;
+ }
+
+ public String getKey() {
+ return chapName;
+ }
+ });
}
return urls;
}
}
- return getImage(null, cover);
+ return getImage(this, null, cover);
}
@Override
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
import java.util.ArrayList;
import java.util.List;
InputStream in = new MarkableFileInputStream(new FileInputStream(
infoFile));
try {
- return createMeta(in);
+ return createMeta(infoFile.toURI().toURL(), in);
} finally {
in.close();
in = null;
}
}
- private static MetaData createMeta(InputStream in) throws IOException {
+ private static MetaData createMeta(URL sourceInfoFile, InputStream in)
+ throws IOException {
MetaData meta = new MetaData();
meta.setTitle(getInfoTag(in, "TITLE"));
meta.setSubject(getInfoTag(in, "SUBJECT"));
meta.setType(getInfoTag(in, "TYPE"));
meta.setImageDocument(getInfoTagBoolean(in, "IMAGES_DOCUMENT", false));
- meta.setCover(BasicSupport.getImage(null, getInfoTag(in, "COVER")));
+ meta.setCover(BasicSupport.getImage(null, sourceInfoFile,
+ getInfoTag(in, "COVER")));
if (meta.getCover() == null) {
meta.setCover(BasicSupport.getDefaultCover(meta.getSubject()));
}
}
- return getImage(source, path);
+ return getImage(this, source, path);
}
@Override