From 92fb0719f84f5b6734b51e528332546d78e9ccec Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Sat, 18 Feb 2017 17:15:30 +0100 Subject: [PATCH] Version 1.1.0 - new Progress reporting system (currently only in CLI mode) - fix on e621 for "pending" pools, which were not downloaded before - unit tests system added (but no test yet, as all tests were moved into nikiroo-utils before release) --- VERSION | 2 +- changelog.md | 43 ++++++++++++++ configure.sh | 2 +- ...es.jar => nikiroo-utils-1.1.0-sources.jar} | Bin 42218 -> 45056 bytes src/be/nikiroo/fanfix/Library.java | 27 ++++++--- src/be/nikiroo/fanfix/Main.java | 53 ++++++++++++++---- src/be/nikiroo/fanfix/reader/BasicReader.java | 27 ++++----- src/be/nikiroo/fanfix/reader/LocalReader.java | 34 +++++++++-- .../fanfix/reader/LocalReaderBook.java | 10 ++-- .../fanfix/reader/LocalReaderFrame.java | 10 ++-- .../fanfix/supported/BasicSupport.java | 22 +++++++- src/be/nikiroo/fanfix/supported/Cbz.java | 14 ++++- src/be/nikiroo/fanfix/supported/E621.java | 5 +- src/be/nikiroo/fanfix/test/Test.java | 24 ++++++++ 14 files changed, 219 insertions(+), 54 deletions(-) create mode 100644 changelog.md rename libs/{nikiroo-utils-1.0.0-sources.jar => nikiroo-utils-1.1.0-sources.jar} (70%) create mode 100644 src/be/nikiroo/fanfix/test/Test.java diff --git a/VERSION b/VERSION index 3eefcb9..9084fa2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.0 +1.1.0 diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..a22be0e --- /dev/null +++ b/changelog.md @@ -0,0 +1,43 @@ +# Fanfix + +## Version 1.1.0 + +- new Progress reporting system (currently only in CLI mode) +- fix on e621 for "pending" pools, which were not downloaded before +- unit tests system added (but no test yet, as all tests were moved into nikiroo-utils) + +## Version 1.0.0 + +The GUI is now good enough to be released (export is still CLI-only though). + +- bugs fixed +- GUI improved (a lot) +- should be good enough for 1.0.0 + +## Version 0.9.5 + +- bugs fixed +- WIN32 compatibility (tested on Windows 10) + +## Version 0.9.4 + +- bugs fixed (lots of) +- perf improved +- use less cache files +- GUI improvement (still not really OK, but OK enough I guess) + +## Version 0.9.3 + +- bugs fixed (lots of) +- first GUI implementation (which is ugly and buggy -- the buggly GUI) + +## Version 0.9.2 + +Minimum JVM version: Java 1.6 (all binary JAR files will be released in 1.6). + +- bugs fixed + +## Version 0.9.1 + +Initial version + diff --git a/configure.sh b/configure.sh index 1da9835..ffdf498 100755 --- a/configure.sh +++ b/configure.sh @@ -44,7 +44,7 @@ else fi; echo "MAIN = be/nikiroo/fanfix/Main" > Makefile -echo "TEST = " >> Makefile +echo "TEST = be/nikiroo/fanfix/test/Test" >> Makefile echo "TEST_PARAMS = $cols $ok $ko" >> Makefile echo "NAME = fanfix" >> Makefile echo "PREFIX = $PREFIX" >> Makefile diff --git a/libs/nikiroo-utils-1.0.0-sources.jar b/libs/nikiroo-utils-1.1.0-sources.jar similarity index 70% rename from libs/nikiroo-utils-1.0.0-sources.jar rename to libs/nikiroo-utils-1.1.0-sources.jar index ab8360ec257451dcbf8b6647bf76043c506d5de7..63466abeaaeb3febce5e9fbe97e58746c2a12297 100644 GIT binary patch delta 9397 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 delta 6546 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 CwjbXB diff --git a/src/be/nikiroo/fanfix/Library.java b/src/be/nikiroo/fanfix/Library.java index 0d9e067..03b584c 100644 --- a/src/be/nikiroo/fanfix/Library.java +++ b/src/be/nikiroo/fanfix/Library.java @@ -14,6 +14,7 @@ import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.output.BasicOutput; import be.nikiroo.fanfix.output.BasicOutput.OutputType; import be.nikiroo.fanfix.supported.BasicSupport; +import be.nikiroo.utils.ui.Progress; import be.nikiroo.fanfix.supported.BasicSupport.SupportType; import be.nikiroo.fanfix.supported.InfoReader; @@ -135,10 +136,12 @@ public class Library { * * @param luid * the Library UID of the story + * @param pg + * the optional progress reporter * * @return the corresponding {@link Story} or NULL if not found */ - public Story getStory(String luid) { + public Story getStory(String luid, Progress pg) { if (luid != null) { for (Entry entry : getStories().entrySet()) { if (luid.equals(entry.getKey().getLuid())) { @@ -147,7 +150,8 @@ public class Library { .getKey().getType()); URL url = entry.getValue().toURI().toURL(); if (type != null) { - return BasicSupport.getSupport(type).process(url); + return BasicSupport.getSupport(type).process(url, + pg); } else { throw new IOException("Unknown type: " + entry.getKey().getType()); @@ -163,6 +167,11 @@ public class Library { } } + if (pg != null) { + pg.setMinMax(0, 1); + pg.setProgress(1); + } + return null; } @@ -172,19 +181,21 @@ public class Library { * * @param url * the {@link URL} to import + * @param pg + * the optional progress reporter * * @return the imported {@link Story} * * @throws IOException * in case of I/O error */ - public Story imprt(URL url) throws IOException { + public Story imprt(URL url, Progress pg) throws IOException { BasicSupport support = BasicSupport.getSupport(url); if (support == null) { throw new IOException("URL not supported: " + url.toString()); } - return save(support.process(url), null); + return save(support.process(url, pg), null); } /** @@ -196,25 +207,27 @@ public class Library { * the {@link OutputType} to transform it to * @param target * the target to save to + * @param pg + * the optional progress reporter * * @return the saved resource (the main saved {@link File}) * * @throws IOException * in case of I/O error */ - public File export(String luid, OutputType type, String target) + public File export(String luid, OutputType type, String target, Progress pg) throws IOException { BasicOutput out = BasicOutput.getOutput(type, true); if (out == null) { throw new IOException("Output type not supported: " + type); } - Story story = getStory(luid); + Story story = getStory(luid, pg); if (story == null) { throw new IOException("Cannot find story to export: " + luid); } - return out.process(getStory(luid), target); + return out.process(story, target); } /** diff --git a/src/be/nikiroo/fanfix/Main.java b/src/be/nikiroo/fanfix/Main.java index f51071d..ed5664a 100644 --- a/src/be/nikiroo/fanfix/Main.java +++ b/src/be/nikiroo/fanfix/Main.java @@ -15,6 +15,7 @@ import be.nikiroo.fanfix.reader.BasicReader.ReaderType; import be.nikiroo.fanfix.supported.BasicSupport; import be.nikiroo.fanfix.supported.BasicSupport.SupportType; import be.nikiroo.utils.UIUtils; +import be.nikiroo.utils.ui.Progress; /** * Main program entry point. @@ -161,17 +162,40 @@ public class Main { } } + final Progress mainProgress = new Progress(0, 80); + mainProgress.addProgressListener(new Progress.ProgressListener() { + private int current = mainProgress.getMin(); + + public void progress(Progress progress, String name) { + int diff = progress.getProgress() - current; + current += diff; + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < diff; i++) { + builder.append('.'); + } + + System.err.print(builder.toString()); + + if (progress.isDone()) { + System.err.println(""); + } + } + }); + Progress pg = new Progress(); + mainProgress.addProgress(pg, mainProgress.getMax()); + if (exitCode != 255) { switch (action) { case IMPORT: - exitCode = imprt(urlString); + exitCode = imprt(urlString, pg); break; case EXPORT: - exitCode = export(luid, typeString, target); + exitCode = export(luid, typeString, target, pg); break; case CONVERT: exitCode = convert(urlString, typeString, target, - plusInfo == null ? false : plusInfo); + plusInfo == null ? false : plusInfo, pg); break; case LIST: exitCode = list(typeString); @@ -238,12 +262,14 @@ public class Main { * * @param urlString * the resource to import + * @param pg + * the optional progress reporter * * @return the exit return code (0 = success) */ - public static int imprt(String urlString) { + public static int imprt(String urlString, Progress pg) { try { - Story story = Instance.getLibrary().imprt(getUrl(urlString)); + Story story = Instance.getLibrary().imprt(getUrl(urlString), pg); System.out.println(story.getMeta().getLuid() + ": \"" + story.getMeta().getTitle() + "\" imported."); } catch (IOException e) { @@ -263,10 +289,13 @@ public class Main { * the {@link OutputType} to use * @param target * the target + * @param pg + * the optional progress reporter * * @return the exit return code (0 = success) */ - public static int export(String luid, String typeString, String target) { + public static int export(String luid, String typeString, String target, + Progress pg) { OutputType type = OutputType.valueOfNullOkUC(typeString); if (type == null) { Instance.syserr(new Exception(trans(StringId.OUTPUT_DESC, @@ -275,7 +304,7 @@ public class Main { } try { - Instance.getLibrary().export(luid, type, target); + Instance.getLibrary().export(luid, type, target, pg); } catch (IOException e) { Instance.syserr(e); return 4; @@ -318,9 +347,9 @@ public class Main { try { BasicReader reader = BasicReader.getReader(); if (library) { - reader.setStory(story); + reader.setStory(story, null); } else { - reader.setStory(getUrl(story)); + reader.setStory(getUrl(story), null); } if (chapString != null) { @@ -354,11 +383,13 @@ public class Main { * @param infoCover * TRUE to also export the cover and info file, even if the given * {@link OutputType} does not usually save them + * @param pg + * the optional progress reporter * * @return the exit return code (0 = success) */ private static int convert(String urlString, String typeString, - String target, boolean infoCover) { + String target, boolean infoCover, Progress pg) { int exitCode = 0; String sourceName = urlString; @@ -380,7 +411,7 @@ public class Main { BasicSupport support = BasicSupport.getSupport(source); if (support != null) { - Story story = support.process(source); + Story story = support.process(source, pg); try { target = new File(target).getAbsolutePath(); diff --git a/src/be/nikiroo/fanfix/reader/BasicReader.java b/src/be/nikiroo/fanfix/reader/BasicReader.java index eabbe7e..bc3bf72 100644 --- a/src/be/nikiroo/fanfix/reader/BasicReader.java +++ b/src/be/nikiroo/fanfix/reader/BasicReader.java @@ -8,6 +8,7 @@ import be.nikiroo.fanfix.Library; import be.nikiroo.fanfix.bundles.Config; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.supported.BasicSupport; +import be.nikiroo.utils.ui.Progress; /** * The class that handles the different {@link Story} readers you can use. @@ -78,23 +79,16 @@ public abstract class BasicReader { * * @param luid * the {@link Story} ID + * @param pg + * the optional progress reporter + * * @throws IOException * in case of I/O error */ - public void setStory(String luid) throws IOException { - story = Instance.getLibrary().getStory(luid); + public void setStory(String luid, Progress pg) throws IOException { + story = Instance.getLibrary().getStory(luid, pg); if (story == null) { - // if the LUID is wrong and < 3, pad it to 3 chars with "0" then - // retry (since LUIDs are %03d) - if (luid != null && luid.length() < 3) { - while (luid.length() < 3) { - luid = "0" + luid; - } - setStory(luid); - } else { - throw new IOException("Cannot retrieve story from library: " - + luid); - } + throw new IOException("Cannot retrieve story from library: " + luid); } } @@ -103,16 +97,19 @@ public abstract class BasicReader { * * @param source * the {@link Story} {@link URL} + * @param pg + * the optional progress reporter + * * @throws IOException * in case of I/O error */ - public void setStory(URL source) throws IOException { + public void setStory(URL source, Progress pg) throws IOException { BasicSupport support = BasicSupport.getSupport(source); if (support == null) { throw new IOException("URL not supported: " + source.toString()); } - story = support.process(source); + story = support.process(source, pg); if (story == null) { throw new IOException( "Cannot retrieve story from external source: " diff --git a/src/be/nikiroo/fanfix/reader/LocalReader.java b/src/be/nikiroo/fanfix/reader/LocalReader.java index c17e83e..88ffc5d 100644 --- a/src/be/nikiroo/fanfix/reader/LocalReader.java +++ b/src/be/nikiroo/fanfix/reader/LocalReader.java @@ -9,6 +9,7 @@ import be.nikiroo.fanfix.Library; import be.nikiroo.fanfix.bundles.UiConfig; import be.nikiroo.fanfix.data.Story; import be.nikiroo.fanfix.output.BasicOutput.OutputType; +import be.nikiroo.utils.ui.Progress; class LocalReader extends BasicReader { private Library lib; @@ -46,10 +47,20 @@ class LocalReader extends BasicReader { public void read(int chapter) { } - // keep same luid - public void imprt(String luid) throws IOException { + /** + * Import the story into the local reader library, and keep the same LUID. + * + * @param luid + * the Library UID + * @param pg + * the optional progress reporter + * + * @throws IOException + * in case of I/O error + */ + public void imprt(String luid, Progress pg) throws IOException { try { - Story story = Instance.getLibrary().getStory(luid); + Story story = Instance.getLibrary().getStory(luid, pg); if (story != null) { story = lib.save(story, luid); } else { @@ -62,10 +73,23 @@ class LocalReader extends BasicReader { } } - public File getTarget(String luid) throws IOException { + /** + * Get the target file related to this {@link Story}. + * + * @param luid + * the LUID of the {@link Story} + * @param pg + * the optional progress reporter + * + * @return the target file + * + * @throws IOException + * in case of I/O error + */ + public File getTarget(String luid, Progress pg) throws IOException { File file = lib.getFile(luid); if (file == null) { - imprt(luid); + imprt(luid, pg); file = lib.getFile(luid); } diff --git a/src/be/nikiroo/fanfix/reader/LocalReaderBook.java b/src/be/nikiroo/fanfix/reader/LocalReaderBook.java index 8e353d9..e7bea6a 100644 --- a/src/be/nikiroo/fanfix/reader/LocalReaderBook.java +++ b/src/be/nikiroo/fanfix/reader/LocalReaderBook.java @@ -31,7 +31,7 @@ class LocalReaderBook extends JPanel { * * @author niki */ - interface BookActionListner extends EventListener { + interface BookActionListener extends EventListener { /** * The book was selected (single click). * @@ -67,7 +67,7 @@ class LocalReaderBook extends JPanel { private boolean hovered; private Date lastClick; private long doubleClickDelay = 200; // in ms - private List listeners; + private List listeners; public LocalReaderBook(MetaData meta) { if (meta.getCover() != null) { @@ -134,7 +134,7 @@ class LocalReaderBook extends JPanel { } private void setupListeners() { - listeners = new ArrayList(); + listeners = new ArrayList(); addMouseListener(new MouseListener() { public void mouseReleased(MouseEvent e) { } @@ -164,7 +164,7 @@ class LocalReaderBook extends JPanel { } private void click(boolean doubleClick) { - for (BookActionListner listener : listeners) { + for (BookActionListener listener : listeners) { if (doubleClick) { listener.action(this); } else { @@ -173,7 +173,7 @@ class LocalReaderBook extends JPanel { } } - public void addActionListener(BookActionListner listener) { + public void addActionListener(BookActionListener listener) { listeners.add(listener); } diff --git a/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java b/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java index a7c743c..d431d8e 100644 --- a/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java +++ b/src/be/nikiroo/fanfix/reader/LocalReaderFrame.java @@ -24,7 +24,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.Main; import be.nikiroo.fanfix.bundles.UiConfig; import be.nikiroo.fanfix.data.MetaData; -import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListner; +import be.nikiroo.fanfix.reader.LocalReaderBook.BookActionListener; import be.nikiroo.utils.WrapLayout; class LocalReaderFrame extends JFrame { @@ -89,7 +89,7 @@ class LocalReaderFrame extends JFrame { books.add(book); final String luid = meta.getLuid(); - book.addActionListener(new BookActionListner() { + book.addActionListener(new BookActionListener() { public void select(LocalReaderBook book) { for (LocalReaderBook abook : books) { abook.setSelected(abook == book); @@ -98,8 +98,8 @@ class LocalReaderFrame extends JFrame { public void action(LocalReaderBook book) { try { - File target = LocalReaderFrame.this.reader - .getTarget(luid); + File target = LocalReaderFrame.this.reader.getTarget( + luid, null); Desktop.getDesktop().browse(target.toURI()); } catch (IOException e) { Instance.syserr(e); @@ -128,7 +128,7 @@ class LocalReaderFrame extends JFrame { + "unresponsive until it is downloaded...", "Importing from URL", JOptionPane.QUESTION_MESSAGE); if (url != null && !url.isEmpty()) { - if (Main.imprt(url) != 0) { + if (Main.imprt(url, null) != 0) { JOptionPane.showMessageDialog(LocalReaderFrame.this, "Cannot import: " + url, "Imort error", JOptionPane.ERROR_MESSAGE); diff --git a/src/be/nikiroo/fanfix/supported/BasicSupport.java b/src/be/nikiroo/fanfix/supported/BasicSupport.java index 9315596..c47d05e 100644 --- a/src/be/nikiroo/fanfix/supported/BasicSupport.java +++ b/src/be/nikiroo/fanfix/supported/BasicSupport.java @@ -24,6 +24,7 @@ import be.nikiroo.fanfix.data.Paragraph.ParagraphType; import be.nikiroo.fanfix.data.Story; import be.nikiroo.utils.IOUtils; import be.nikiroo.utils.StringUtils; +import be.nikiroo.utils.ui.Progress; /** * This class is the base class used by the other support classes. It can be @@ -328,26 +329,42 @@ public abstract class BasicSupport { * * @param url * the story resource + * @param pg + * the optional progress reporter * * @return the {@link Story} * * @throws IOException * in case of I/O error */ - public Story process(URL url) throws IOException { + public Story process(URL url, Progress pg) throws IOException { + if (pg == null) { + pg = new Progress(); + } else { + pg.setMinMax(0, 100); + } + setCurrentReferer(url); + pg.setProgress(1); try { Story story = processMeta(url, false, true); + pg.setProgress(10); if (story == null) { + pg.setProgress(100); return null; } story.setChapters(new ArrayList()); List> chapters = getChapters(url, getInput()); + pg.setProgress(20); + int i = 1; if (chapters != null) { + Progress pgChaps = new Progress(0, chapters.size()); + pg.addProgress(pgChaps, 80); + for (Entry chap : chapters) { setCurrentReferer(chap.getValue()); InputStream chapIn = Instance.getCache().open( @@ -360,8 +377,11 @@ public abstract class BasicSupport { chapIn.close(); } + pgChaps.setProgress(i); i++; } + } else { + pg.setProgress(100); } return story; diff --git a/src/be/nikiroo/fanfix/supported/Cbz.java b/src/be/nikiroo/fanfix/supported/Cbz.java index 1080ad2..295dc15 100644 --- a/src/be/nikiroo/fanfix/supported/Cbz.java +++ b/src/be/nikiroo/fanfix/supported/Cbz.java @@ -14,6 +14,7 @@ import be.nikiroo.fanfix.Instance; import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.Paragraph; import be.nikiroo.fanfix.data.Story; +import be.nikiroo.utils.ui.Progress; /** * Support class for CBZ files (works better with CBZ created with this program, @@ -54,7 +55,13 @@ class Cbz extends Epub { } @Override - public Story process(URL url) throws IOException { + public Story process(URL url, Progress pg) throws IOException { + if (pg == null) { + pg = new Progress(); + } else { + pg.setMinMax(0, 100); + } + Story story = processMeta(url, false, true); story.setChapters(new ArrayList()); Chapter chap = new Chapter(1, null); @@ -62,6 +69,7 @@ class Cbz extends Epub { ZipInputStream zipIn = new ZipInputStream(getInput()); + pg.setProgress(10); List images = new ArrayList(); for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn .getNextEntry()) { @@ -87,8 +95,11 @@ class Cbz extends Epub { } } + pg.setProgress(80); + // ZIP order is not sure Collections.sort(images); + pg.setProgress(90); for (String uuid : images) { try { @@ -99,6 +110,7 @@ class Cbz extends Epub { } } + pg.setProgress(100); return story; } } diff --git a/src/be/nikiroo/fanfix/supported/E621.java b/src/be/nikiroo/fanfix/supported/E621.java index 665bdd5..5ebd6b3 100644 --- a/src/be/nikiroo/fanfix/supported/E621.java +++ b/src/be/nikiroo/fanfix/supported/E621.java @@ -14,6 +14,7 @@ import be.nikiroo.fanfix.data.Chapter; import be.nikiroo.fanfix.data.MetaData; import be.nikiroo.fanfix.data.Story; import be.nikiroo.utils.StringUtils; +import be.nikiroo.utils.ui.Progress; /** * Support class for e621.net and