import be.nikiroo.fanfix.bundles.UiConfigBundle;
import be.nikiroo.fanfix.library.BasicLibrary;
import be.nikiroo.fanfix.library.LocalLibrary;
-import be.nikiroo.fanfix.output.BasicOutput.OutputType;
import be.nikiroo.utils.IOUtils;
import be.nikiroo.utils.resources.Bundles;
uiconfig = new UiConfigBundle();
trans = new StringIdBundle(getLang());
try {
- lib = new LocalLibrary(getFile(Config.LIBRARY_DIR),
- OutputType.INFO_TEXT, OutputType.CBZ);
+ lib = new LocalLibrary(getFile(Config.LIBRARY_DIR));
} catch (Exception e) {
syserr(new IOException("Cannot create library for directory: "
+ getFile(Config.LIBRARY_DIR), e));
coverDir = getFile(Config.DEFAULT_COVERS_DIR);
File tmp = getFile(Config.CACHE_DIR);
readerTmp = getFile(UiConfig.CACHE_DIR_LOCAL_READER);
- remoteDir = new File(getFile(Config.LIBRARY_DIR), "remote");
+ remoteDir = new File(configDir, "remote");
if (checkEnv("NOUTF")) {
trans.setUnicode(false);
*/
public static int export(String luid, String typeString, String target,
Progress pg) {
- OutputType type = OutputType.valueOfNullOkUC(typeString);
+ OutputType type = OutputType.valueOfNullOkUC(typeString, null);
if (type == null) {
Instance.syserr(new Exception(trans(StringId.OUTPUT_DESC,
typeString)));
sourceName = sourceName.substring("file://".length());
}
- OutputType type = OutputType.valueOfAllOkUC(typeString);
+ OutputType type = OutputType.valueOfAllOkUC(typeString, null);
if (type == null) {
Instance.syserr(new IOException(trans(
StringId.ERR_BAD_OUTPUT_TYPE, typeString)));
@Meta(description = "reader type (CLI = simple output to console, TUI = Text User Interface with menus and windows, GUI = a GUI with locally stored files)", format = Format.FIXED_LIST, list = {
"CLI", "GUI", "TUI" }, info = "Select the default reader to use to read stories")
READER_TYPE, //
+ @Meta(format = Format.COMBO_LIST, list = { "INFO_TEXT", "EPUB", "HTML",
+ "TEXT" }, info = "One of the known output type", description = "The type of output for the Local Reader for non-images documents")
+ NON_IMAGES_DOCUMENT_TYPE, //
+ @Meta(format = Format.COMBO_LIST, list = { "CBZ", "HTML" }, description = "The type of output for the Local Reader for images documents")
+ IMAGES_DOCUMENT_TYPE, //
@Meta(description = "absolute path, $HOME variable supported, / is always accepted as dir separator", format = Format.DIRECTORY, info = "The directory where to store temporary files, defaults to directory 'tmp' in the conig directory (usually $HOME/.fanfix)")
CACHE_DIR, //
@Meta(description = "delay in hours, or 0 for no cache, or -1 for infinite time (default)", format = Format.INT, info = "The delay after which a cached resource that is thought to change ~often is considered too old and triggers a refresh")
public enum UiConfig {
@Meta(format = Format.DIRECTORY, info = "absolute path, $HOME variable supported, / is always accepted as dir separator", description = "The directory where to store temporary files, defaults to directory 'tmp.reader' in the conig directory (usually $HOME/.fanfix)")
CACHE_DIR_LOCAL_READER, //
- @Meta(format = Format.COMBO_LIST, list = { "HTML", "CBZ" }, info = "One of the known output type", description = "The type of output for the Local Reader for non-images documents")
- NON_IMAGES_DOCUMENT_TYPE, //
- @Meta(format = Format.COMBO_LIST, list = { "HTML", "CBZ" }, description = "The type of output for the Local Reader for images documents")
- IMAGES_DOCUMENT_TYPE, //
+ @Meta(format = Format.COMBO_LIST, list = { "INFO_TEXT", "EPUB", "HTML",
+ "TEXT" }, info = "One of the known output type", description = "The type of output for the GUI Reader for non-images documents")
+ GUI_NON_IMAGES_DOCUMENT_TYPE, //
+ @Meta(format = Format.COMBO_LIST, list = { "CBZ", "HTML" }, description = "The type of output for the GUI Reader for images documents")
+ GUI_IMAGES_DOCUMENT_TYPE, //
@Meta(info = "A command to start", description = "The command launched for images documents -- default to the system default for the current file type")
IMAGES_DOCUMENT_READER, //
@Meta(info = "A command to start", description = "The command launched for non images documents -- default to the system default for the current file type")
# (FORMAT: FIXED_LIST) Select the default reader to use to read stories
# ALLOWED VALUES: "CLI" "GUI" "TUI"
READER_TYPE =
+# The type of output for the Local Reader for non-images documents
+# (FORMAT: COMBO_LIST) One of the known output type
+# ALLOWED VALUES: "INFO_TEXT" "EPUB" "HTML" "TEXT"
+NON_IMAGES_DOCUMENT_TYPE = INFO_TEXT
+# The type of output for the Local Reader for images documents
+# (FORMAT: COMBO_LIST)
+# ALLOWED VALUES: "CBZ" "HTML"
+IMAGES_DOCUMENT_TYPE = CBZ
# absolute path, $HOME variable supported, / is always accepted as dir separator
# (FORMAT: DIRECTORY) The directory where to store temporary files, defaults to directory 'tmp' in the conig directory (usually $HOME/.fanfix)
CACHE_DIR =
LOGIN_FIMFICTION_APIKEY_FORCE_HTML =
# A token is required to use the beta APIv2 from FimFiction (see APIKEY_CLIENT_*)
# (FORMAT: PASSWORD)
-LOGIN_FIMFICTION_APIKEY_TOKEN = Bearer WnZ5oHlzQoDocv1GcgHfcoqctHkSwL-D
+LOGIN_FIMFICTION_APIKEY_TOKEN = Bearer WnZ5oHlzQoDocv1GcgHfcoqctHkSwL-D
\t--list: list the stories present in the library\n\
\t--set-reader [reader type]: set the reader type to CLI, TUI or GUI for \n\
\t\tthis command\n\
+\t--server [port]: start a remote server on this port\n\
\t--remote [host] [port]: select this remote server to get \n\
\t\t(or update or...) the stories from\n\
\t--help: this help message\n\
# The directory where to store temporary files, defaults to directory 'tmp.reader' in the conig directory (usually $HOME/.fanfix)
# (FORMAT: DIRECTORY) absolute path, $HOME variable supported, / is always accepted as dir separator
CACHE_DIR_LOCAL_READER =
-# The type of output for the Local Reader for non-images documents
+# The type of output for the GUI Reader for non-images documents
# (FORMAT: COMBO_LIST) One of the known output type
-# ALLOWED VALUES: "HTML" "CBZ"
-NON_IMAGES_DOCUMENT_TYPE = HTML
-# The type of output for the Local Reader for images documents
+# ALLOWED VALUES: "INFO_TEXT" "EPUB" "HTML" "TEXT"
+GUI_NON_IMAGES_DOCUMENT_TYPE = HTML
+# The type of output for the GUI Reader for images documents
# (FORMAT: COMBO_LIST)
-# ALLOWED VALUES: "HTML" "CBZ"
-IMAGES_DOCUMENT_TYPE = CBZ
+# ALLOWED VALUES: "CBZ" "HTML"
+GUI_IMAGES_DOCUMENT_TYPE = CBZ
# The command launched for images documents -- default to the system default for the current file type
# (FORMAT: STRING) A command to start
IMAGES_DOCUMENT_READER =
# The directory where to store temporary files, defaults to directory 'tmp.reader' in the conig directory (usually $HOME/.fanfix)
# (FORMAT: DIRECTORY) absolute path, $HOME variable supported, / is always accepted as dir separator
CACHE_DIR_LOCAL_READER = The directory where to store temporary files, defaults to directory 'tmp.reader' in the config directory (usually $HOME/.fanfix) -- this is an absolute path, $HOME variable supported, / is always accepted as dir separator
-# The type of output for the Local Reader for non-images documents
+# The type of output for the GUI Reader for non-images documents
# (FORMAT: COMBO_LIST) One of the known output type
-# ALLOWED VALUES: "HTML" "CBZ"
-NON_IMAGES_DOCUMENT_TYPE =
-# The type of output for the Local Reader for images documents
+# ALLOWED VALUES: "INFO_TEXT" "EPUB" "HTML" "TEXT"
+GUI_NON_IMAGES_DOCUMENT_TYPE =
+# The type of output for the GUI Reader for images documents
# (FORMAT: COMBO_LIST)
-# ALLOWED VALUES: "HTML" "CBZ"
-IMAGES_DOCUMENT_TYPE =
+# ALLOWED VALUES: "CBZ" "HTML"
+GUI_IMAGES_DOCUMENT_TYPE =
# The command launched for images documents -- default to the system default for the current file type
# (FORMAT: STRING) A command to start
IMAGES_DOCUMENT_READER =
private OutputType text;
private OutputType image;
+ /**
+ * Create a new {@link LocalLibrary} with the given back-end directory.
+ *
+ * @param baseDir
+ * the directory where to find the {@link Story} objects
+ */
+ public LocalLibrary(File baseDir) {
+ this(baseDir, Instance.getConfig().getString(
+ Config.NON_IMAGES_DOCUMENT_TYPE), Instance.getConfig()
+ .getString(Config.IMAGES_DOCUMENT_TYPE), false);
+ }
+
+ /**
+ * Create a new {@link LocalLibrary} with the given back-end directory.
+ *
+ * @param baseDir
+ * the directory where to find the {@link Story} objects
+ */
+ public LocalLibrary(File baseDir, String text, String image,
+ boolean defaultIsHtml) {
+ this(baseDir, OutputType.valueOfNullOkUC(text,
+ defaultIsHtml ? OutputType.HTML : OutputType.INFO_TEXT),
+ OutputType.valueOfNullOkUC(image,
+ defaultIsHtml ? OutputType.HTML : OutputType.CBZ));
+ }
+
/**
* Create a new {@link LocalLibrary} with the given back-end directory.
*
* @param baseDir
* the directory where to find the {@link Story} objects
* @param text
- * the {@link OutputType} to save the text-focused stories into
+ * the {@link OutputType} to use for non-image documents
* @param image
- * the {@link OutputType} to save the images-focused stories into
+ * the {@link OutputType} to use for image documents
*/
public LocalLibrary(File baseDir, OutputType text, OutputType image) {
this.baseDir = baseDir;
pg = new Progress();
}
- // Check if we can simply copy the files instead of the whole process
+ LocalLibrary otherLocalLibrary = null;
+ if (other instanceof RemoteLibrary) {
+ otherLocalLibrary = ((RemoteLibrary) other).getLocalLibrary();
+ }
+
if (other instanceof LocalLibrary) {
- LocalLibrary otherLibrary = (LocalLibrary) other;
- MetaData meta = otherLibrary.getInfo(luid);
- String expectedType = "" + (meta.isImageDocument() ? image : text);
- if (meta.getType().equals(expectedType)) {
- File from = otherLibrary.getExpectedDir(meta.getSource());
+ otherLocalLibrary = (LocalLibrary) other;
+ }
+
+ // Check if we can simply copy the files instead of the whole process
+ if (otherLocalLibrary != null) {
+ MetaData meta = otherLocalLibrary.getInfo(luid);
+ String expectedType = ""
+ + (meta != null && meta.isImageDocument() ? image : text);
+ if (meta != null && meta.getType().equals(expectedType)) {
+ File from = otherLocalLibrary.getExpectedDir(meta.getSource());
File to = this.getExpectedDir(meta.getSource());
- List<File> sources = otherLibrary.getRelatedFiles(luid);
+ List<File> sources = otherLocalLibrary.getRelatedFiles(luid);
if (!sources.isEmpty()) {
pg.setMinMax(0, sources.size());
}
File target = new File(source.getAbsolutePath().replace(
from.getAbsolutePath(), to.getAbsolutePath()));
if (!source.equals(target)) {
+ target.getParentFile().mkdirs();
InputStream in = null;
try {
in = new FileInputStream(source);
}
super.imprt(other, luid, pg);
+
+ clearCache();
}
/**
import be.nikiroo.fanfix.Instance;
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Story;
-import be.nikiroo.fanfix.output.BasicOutput.OutputType;
import be.nikiroo.utils.Progress;
import be.nikiroo.utils.Version;
import be.nikiroo.utils.serial.ConnectActionClient;
this.baseDir = Instance.getRemoteDir(host);
this.baseDir.mkdirs();
- this.lib = new LocalLibrary(baseDir, OutputType.INFO_TEXT,
- OutputType.CBZ);
+ this.lib = new LocalLibrary(baseDir);
}
@Override
metas = new ArrayList<MetaData>();
try {
- new ConnectActionClient(host, port, true, null) {
+ new ConnectActionClient(host, port, true) {
@Override
public void action(Version serverVersion) throws Exception {
try {
} catch (IOException e) {
Instance.syserr(e);
}
+
+ List<String> test = new ArrayList<String>();
+ for (MetaData meta : metas) {
+ if (test.contains(meta.getLuid())) {
+ throw new RuntimeException("wwops");
+ }
+ test.add(meta.getLuid());
+ }
}
return metas;
if (file == null) {
final File[] tmp = new File[1];
try {
- new ConnectActionClient(host, port, true, null) {
+ new ConnectActionClient(host, port, true) {
@Override
public void action(Version serverVersion) throws Exception {
try {
}
@Override
- public BufferedImage getCover(String luid) {
- // Retrieve it from the network if needed:
- if (lib.getInfo(luid) == null) {
- getFile(luid);
+ public BufferedImage getCover(final String luid) {
+ // Retrieve it from the cache if possible:
+ if (lib.getInfo(luid) != null) {
+ return lib.getCover(luid);
+ }
+
+ final BufferedImage[] result = new BufferedImage[1];
+ try {
+ new ConnectActionClient(host, port, true) {
+ @Override
+ public void action(Version serverVersion) throws Exception {
+ try {
+ Object rep = send("GET_COVER " + luid);
+ result[0] = (BufferedImage) rep;
+ } catch (Exception e) {
+ Instance.syserr(e);
+ }
+ }
+ }.connect();
+ } catch (IOException e) {
+ Instance.syserr(e);
}
- return lib.getCover(luid);
+ return result[0];
}
@Override
protected Story doSave(Story story, Progress pg) throws IOException {
throw new java.lang.InternalError("Should not have been called");
}
+
+ /**
+ * Return the backing local library.
+ *
+ * @return the library
+ */
+ LocalLibrary getLocalLibrary() {
+ return lib;
+ }
}
if (args != null) {
return Instance.getLibrary().getStory(args, null);
}
+ } else if ("GET_COVER".equals(command)) {
+ if (args != null) {
+ return Instance.getLibrary().getCover(args);
+ }
}
return null;
/**
* Call {@link OutputType#valueOf(String)} after conversion to upper
- * case but return NULL for NULL and empty instead of raising an
+ * case but return def for NULL and empty instead of raising an
* exception.
*
* @param typeName
* the possible type name
+ * @param def
+ * the default value
*
* @return NULL or the type
*/
- public static OutputType valueOfNullOkUC(String typeName) {
+ public static OutputType valueOfNullOkUC(String typeName, OutputType def) {
if (typeName == null || typeName.isEmpty()) {
- return null;
+ return def;
}
return OutputType.valueOfUC(typeName);
/**
* Call {@link OutputType#valueOf(String)} after conversion to upper
- * case but return NULL in case of error instead of raising an
- * exception.
+ * case but return def in case of error instead of raising an exception.
*
* @param typeName
* the possible type name
+ * @param def
+ * the default value
*
* @return NULL or the type
*/
- public static OutputType valueOfAllOkUC(String typeName) {
+ public static OutputType valueOfAllOkUC(String typeName, OutputType def) {
try {
return OutputType.valueOfUC(typeName);
} catch (Exception e) {
- return null;
+ return def;
}
}
}
import be.nikiroo.fanfix.data.MetaData;
import be.nikiroo.fanfix.data.Story;
import be.nikiroo.fanfix.library.LocalLibrary;
-import be.nikiroo.fanfix.output.BasicOutput.OutputType;
import be.nikiroo.utils.Progress;
import be.nikiroo.utils.Version;
import be.nikiroo.utils.ui.UIUtils;
"Cannote create cache directory for local reader: " + dir);
}
- OutputType text = null;
- OutputType images = null;
-
- try {
- text = OutputType.valueOfNullOkUC(Instance.getUiConfig().getString(
- UiConfig.NON_IMAGES_DOCUMENT_TYPE));
- if (text == null) {
- text = OutputType.HTML;
- }
-
- images = OutputType.valueOfNullOkUC(Instance.getUiConfig()
- .getString(UiConfig.IMAGES_DOCUMENT_TYPE));
- if (images == null) {
- images = OutputType.CBZ;
- }
- } catch (Exception e) {
- UiConfig key = (text == null) ? UiConfig.NON_IMAGES_DOCUMENT_TYPE
- : UiConfig.IMAGES_DOCUMENT_TYPE;
- String value = Instance.getUiConfig().getString(key);
-
- throw new IOException(
- String.format(
- "The configuration option %s is not valid: %s",
- key, value), e);
- }
-
- localLibrary = new LocalLibrary(dir, text, images);
+ localLibrary = new LocalLibrary(dir, Instance.getUiConfig().getString(
+ UiConfig.GUI_NON_IMAGES_DOCUMENT_TYPE), Instance.getUiConfig()
+ .getString(UiConfig.GUI_IMAGES_DOCUMENT_TYPE), true);
}
@Override
BufferedImage resizedImage = null;
String id = null;
- if (meta.getLuid() != null) {
- id = meta.getUuid() + ".thumb_" + SPINE_WIDTH + "x" + COVER_WIDTH
- + "+" + SPINE_HEIGHT + "+" + COVER_HEIGHT + "@" + HOFFSET;
- InputStream in = Instance.getCache().getFromCache(id);
- if (in != null) {
- try {
- resizedImage = ImageUtils.fromStream(in);
- in.close();
- in = null;
- } catch (IOException e) {
- Instance.syserr(e);
- }
+ String key = meta.getUuid();
+ if (key == null) {
+ // a fake meta (a source)
+ key = "source_" + meta.getSource();
+ }
+
+ id = key + ".thumb_" + SPINE_WIDTH + "x" + COVER_WIDTH + "+"
+ + SPINE_HEIGHT + "+" + COVER_HEIGHT + "@" + HOFFSET;
+ InputStream in = Instance.getCache().getFromCache(id);
+ if (in != null) {
+ try {
+ resizedImage = ImageUtils.fromStream(in);
+ in.close();
+ in = null;
+ } catch (IOException e) {
+ Instance.syserr(e);
}
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ImageIO.write(resizedImage, "png", out);
byte[] imageBytes = out.toByteArray();
- InputStream in = new ByteArrayInputStream(imageBytes);
+ in = new ByteArrayInputStream(imageBytes);
Instance.getCache().addToCache(in, id);
in.close();
in = null;
import java.util.ArrayList;
import java.util.List;
+import javax.management.RuntimeErrorException;
import javax.swing.JLabel;
import javax.swing.JPanel;