mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-04 18:29:23 +02:00
store end position in bookmarks; set end position for new bookmarks
This commit is contained in:
parent
7f5257d2fc
commit
bc3f86c3fe
6 changed files with 213 additions and 109 deletions
|
@ -646,6 +646,7 @@ public final class FBReader extends Activity {
|
|||
myFBReaderApp.Model.Book,
|
||||
fbView.getModel().getId(),
|
||||
fbView.getSelectionStartPosition(),
|
||||
fbView.getSelectionEndPosition(),
|
||||
text,
|
||||
true
|
||||
);
|
||||
|
|
|
@ -839,7 +839,8 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
final StringBuilder sql = new StringBuilder("SELECT")
|
||||
.append(" bm.bookmark_id,bm.book_id,b.title,bm.bookmark_text,")
|
||||
.append("bm.creation_time,bm.modification_time,bm.access_time,bm.access_counter,")
|
||||
.append("bm.model_id,bm.paragraph,bm.word,bm.char")
|
||||
.append("bm.model_id,bm.paragraph,bm.word,bm.char,")
|
||||
.append("bm.end_paragraph,bm.end_word,bm.end_character,")
|
||||
.append(" FROM Bookmarks AS bm INNER JOIN Books AS b ON b.book_id = bm.book_id")
|
||||
.append(" WHERE");
|
||||
if (query.Book != null) {
|
||||
|
@ -864,7 +865,10 @@ final class SQLiteBooksDatabase extends BooksDatabase {
|
|||
(int)cursor.getLong(9),
|
||||
(int)cursor.getLong(10),
|
||||
(int)cursor.getLong(11),
|
||||
true
|
||||
(int)cursor.getLong(12),
|
||||
cursor.isNull(13) ? -1 : (int)cursor.getLong(13),
|
||||
cursor.isNull(14) ? -1 : (int)cursor.getLong(14),
|
||||
query.Visible
|
||||
));
|
||||
}
|
||||
cursor.close();
|
||||
|
|
|
@ -40,12 +40,21 @@ public final class Bookmark extends ZLTextFixedPosition {
|
|||
private Date myAccessDate;
|
||||
private int myAccessCount;
|
||||
private Date myLatestDate;
|
||||
private ZLTextFixedPosition myEnd;
|
||||
private int myLength;
|
||||
|
||||
public final String ModelId;
|
||||
public final boolean IsVisible;
|
||||
|
||||
Bookmark(long id, long bookId, String bookTitle, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCount, String modelId, int paragraphIndex, int elementIndex, int charIndex, boolean isVisible) {
|
||||
super(paragraphIndex, elementIndex, charIndex);
|
||||
Bookmark(
|
||||
long id, long bookId, String bookTitle, String text,
|
||||
Date creationDate, Date modificationDate, Date accessDate, int accessCount,
|
||||
String modelId,
|
||||
int start_paragraphIndex, int start_elementIndex, int start_charIndex,
|
||||
int end_paragraphIndex, int end_elementIndex, int end_charIndex,
|
||||
boolean isVisible
|
||||
) {
|
||||
super(start_paragraphIndex, start_elementIndex, start_charIndex);
|
||||
|
||||
myId = id;
|
||||
myBookId = bookId;
|
||||
|
@ -63,14 +72,128 @@ public final class Bookmark extends ZLTextFixedPosition {
|
|||
myAccessCount = accessCount;
|
||||
ModelId = modelId;
|
||||
IsVisible = isVisible;
|
||||
|
||||
if (end_charIndex >= 0) {
|
||||
myEnd = new ZLTextFixedPosition(end_paragraphIndex, end_elementIndex, end_charIndex);
|
||||
} else {
|
||||
myLength = end_paragraphIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Buffer {
|
||||
final StringBuilder Builder = new StringBuilder();
|
||||
final ZLTextWordCursor Cursor;
|
||||
|
||||
Buffer(ZLTextWordCursor cursor) {
|
||||
Cursor = new ZLTextWordCursor(cursor);
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return Builder.length() == 0;
|
||||
}
|
||||
|
||||
void append(Buffer buffer) {
|
||||
Builder.append(buffer.Builder);
|
||||
Cursor.setCursor(buffer.Cursor);
|
||||
buffer.Builder.delete(0, buffer.Builder.length());
|
||||
}
|
||||
|
||||
void append(CharSequence data) {
|
||||
Builder.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static Bookmark createBookmark(Book book, String modelId, ZLTextWordCursor startCursor, int maxWords, boolean isVisible) {
|
||||
final ZLTextWordCursor cursor = new ZLTextWordCursor(startCursor);
|
||||
|
||||
final Buffer buffer = new Buffer(cursor);
|
||||
final Buffer sentenceBuffer = new Buffer(cursor);
|
||||
final Buffer phraseBuffer = new Buffer(cursor);
|
||||
|
||||
int wordCounter = 0;
|
||||
int sentenceCounter = 0;
|
||||
int storedWordCounter = 0;
|
||||
boolean lineIsNonEmpty = false;
|
||||
boolean appendLineBreak = false;
|
||||
mainLoop:
|
||||
while (wordCounter < maxWords && sentenceCounter < 3) {
|
||||
while (cursor.isEndOfParagraph()) {
|
||||
if (!cursor.nextParagraph()) {
|
||||
break mainLoop;
|
||||
}
|
||||
if (!buffer.isEmpty() && cursor.getParagraphCursor().isEndOfSection()) {
|
||||
break mainLoop;
|
||||
}
|
||||
if (!phraseBuffer.isEmpty()) {
|
||||
sentenceBuffer.append(phraseBuffer);
|
||||
}
|
||||
if (!sentenceBuffer.isEmpty()) {
|
||||
if (appendLineBreak) {
|
||||
buffer.append("\n");
|
||||
}
|
||||
buffer.append(sentenceBuffer);
|
||||
++sentenceCounter;
|
||||
storedWordCounter = wordCounter;
|
||||
}
|
||||
lineIsNonEmpty = false;
|
||||
if (!buffer.isEmpty()) {
|
||||
appendLineBreak = true;
|
||||
}
|
||||
}
|
||||
final ZLTextElement element = cursor.getElement();
|
||||
if (element instanceof ZLTextWord) {
|
||||
final ZLTextWord word = (ZLTextWord)element;
|
||||
if (lineIsNonEmpty) {
|
||||
phraseBuffer.append(" ");
|
||||
}
|
||||
phraseBuffer.Builder.append(word.Data, word.Offset, word.Length);
|
||||
phraseBuffer.Cursor.setCursor(cursor);
|
||||
phraseBuffer.Cursor.setCharIndex(word.Length);
|
||||
++wordCounter;
|
||||
lineIsNonEmpty = true;
|
||||
switch (word.Data[word.Offset + word.Length - 1]) {
|
||||
case ',':
|
||||
case ':':
|
||||
case ';':
|
||||
case ')':
|
||||
sentenceBuffer.append(phraseBuffer);
|
||||
break;
|
||||
case '.':
|
||||
case '!':
|
||||
case '?':
|
||||
++sentenceCounter;
|
||||
if (appendLineBreak) {
|
||||
buffer.append("\n");
|
||||
appendLineBreak = false;
|
||||
}
|
||||
sentenceBuffer.append(phraseBuffer);
|
||||
buffer.append(sentenceBuffer);
|
||||
storedWordCounter = wordCounter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.nextWord();
|
||||
}
|
||||
if (storedWordCounter < 4) {
|
||||
if (sentenceBuffer.isEmpty()) {
|
||||
sentenceBuffer.append(phraseBuffer);
|
||||
}
|
||||
if (appendLineBreak) {
|
||||
buffer.append("\n");
|
||||
}
|
||||
buffer.append(sentenceBuffer);
|
||||
}
|
||||
return new Bookmark(book, modelId, startCursor, buffer.Cursor, buffer.Builder.toString(), isVisible);
|
||||
}
|
||||
|
||||
/*
|
||||
public Bookmark(Book book, String modelId, ZLTextWordCursor cursor, int maxLength, boolean isVisible) {
|
||||
this(book, modelId, cursor, createBookmarkText(cursor, maxLength), isVisible);
|
||||
}
|
||||
*/
|
||||
|
||||
public Bookmark(Book book, String modelId, ZLTextPosition position, String text, boolean isVisible) {
|
||||
super(position);
|
||||
public Bookmark(Book book, String modelId, ZLTextPosition start, ZLTextPosition end, String text, boolean isVisible) {
|
||||
super(start);
|
||||
|
||||
myId = -1;
|
||||
myBookId = book.getId();
|
||||
|
@ -79,6 +202,7 @@ public final class Bookmark extends ZLTextFixedPosition {
|
|||
myCreationDate = new Date();
|
||||
ModelId = modelId;
|
||||
IsVisible = isVisible;
|
||||
myEnd = new ZLTextFixedPosition(end);
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
|
@ -115,6 +239,14 @@ public final class Bookmark extends ZLTextFixedPosition {
|
|||
return myAccessCount;
|
||||
}
|
||||
|
||||
public ZLTextPosition getEnd() {
|
||||
return myEnd;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return myLength;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
if (!text.equals(myText)) {
|
||||
myText = text;
|
||||
|
@ -140,92 +272,6 @@ public final class Bookmark extends ZLTextFixedPosition {
|
|||
}
|
||||
}
|
||||
|
||||
private static String createBookmarkText(ZLTextWordCursor cursor, int maxWords) {
|
||||
cursor = new ZLTextWordCursor(cursor);
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
final StringBuilder sentenceBuilder = new StringBuilder();
|
||||
final StringBuilder phraseBuilder = new StringBuilder();
|
||||
|
||||
int wordCounter = 0;
|
||||
int sentenceCounter = 0;
|
||||
int storedWordCounter = 0;
|
||||
boolean lineIsNonEmpty = false;
|
||||
boolean appendLineBreak = false;
|
||||
mainLoop:
|
||||
while (wordCounter < maxWords && sentenceCounter < 3) {
|
||||
while (cursor.isEndOfParagraph()) {
|
||||
if (!cursor.nextParagraph()) {
|
||||
break mainLoop;
|
||||
}
|
||||
if ((builder.length() > 0) && cursor.getParagraphCursor().isEndOfSection()) {
|
||||
break mainLoop;
|
||||
}
|
||||
if (phraseBuilder.length() > 0) {
|
||||
sentenceBuilder.append(phraseBuilder);
|
||||
phraseBuilder.delete(0, phraseBuilder.length());
|
||||
}
|
||||
if (sentenceBuilder.length() > 0) {
|
||||
if (appendLineBreak) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append(sentenceBuilder);
|
||||
sentenceBuilder.delete(0, sentenceBuilder.length());
|
||||
++sentenceCounter;
|
||||
storedWordCounter = wordCounter;
|
||||
}
|
||||
lineIsNonEmpty = false;
|
||||
if (builder.length() > 0) {
|
||||
appendLineBreak = true;
|
||||
}
|
||||
}
|
||||
final ZLTextElement element = cursor.getElement();
|
||||
if (element instanceof ZLTextWord) {
|
||||
final ZLTextWord word = (ZLTextWord)element;
|
||||
if (lineIsNonEmpty) {
|
||||
phraseBuilder.append(" ");
|
||||
}
|
||||
phraseBuilder.append(word.Data, word.Offset, word.Length);
|
||||
++wordCounter;
|
||||
lineIsNonEmpty = true;
|
||||
switch (word.Data[word.Offset + word.Length - 1]) {
|
||||
case ',':
|
||||
case ':':
|
||||
case ';':
|
||||
case ')':
|
||||
sentenceBuilder.append(phraseBuilder);
|
||||
phraseBuilder.delete(0, phraseBuilder.length());
|
||||
break;
|
||||
case '.':
|
||||
case '!':
|
||||
case '?':
|
||||
++sentenceCounter;
|
||||
if (appendLineBreak) {
|
||||
builder.append("\n");
|
||||
appendLineBreak = false;
|
||||
}
|
||||
sentenceBuilder.append(phraseBuilder);
|
||||
phraseBuilder.delete(0, phraseBuilder.length());
|
||||
builder.append(sentenceBuilder);
|
||||
sentenceBuilder.delete(0, sentenceBuilder.length());
|
||||
storedWordCounter = wordCounter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cursor.nextWord();
|
||||
}
|
||||
if (storedWordCounter < 4) {
|
||||
if (sentenceBuilder.length() == 0) {
|
||||
sentenceBuilder.append(phraseBuilder);
|
||||
}
|
||||
if (appendLineBreak) {
|
||||
builder.append("\n");
|
||||
}
|
||||
builder.append(sentenceBuilder);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
void setId(long id) {
|
||||
myId = id;
|
||||
}
|
||||
|
|
|
@ -86,8 +86,22 @@ public abstract class BooksDatabase {
|
|||
protected abstract void setLabel(long bookId, String label);
|
||||
protected abstract void removeLabel(long bookId, String label);
|
||||
|
||||
protected Bookmark createBookmark(long id, long bookId, String bookTitle, String text, Date creationDate, Date modificationDate, Date accessDate, int accessCounter, String modelId, int paragraphIndex, int wordIndex, int charIndex, boolean isVisible) {
|
||||
return new Bookmark(id, bookId, bookTitle, text, creationDate, modificationDate, accessDate, accessCounter, modelId, paragraphIndex, wordIndex, charIndex, isVisible);
|
||||
protected Bookmark createBookmark(
|
||||
long id, long bookId, String bookTitle, String text,
|
||||
Date creationDate, Date modificationDate, Date accessDate, int accessCounter,
|
||||
String modelId,
|
||||
int start_paragraphIndex, int start_wordIndex, int start_charIndex,
|
||||
int end_paragraphIndex, int end_wordIndex, int end_charIndex,
|
||||
boolean isVisible
|
||||
) {
|
||||
return new Bookmark(
|
||||
id, bookId, bookTitle, text,
|
||||
creationDate, modificationDate, accessDate, accessCounter,
|
||||
modelId,
|
||||
start_paragraphIndex, start_wordIndex, start_charIndex,
|
||||
end_paragraphIndex, end_wordIndex, end_charIndex,
|
||||
isVisible
|
||||
);
|
||||
}
|
||||
|
||||
protected abstract List<Bookmark> loadBookmarks(BookmarkQuery query);
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.text.ParseException;
|
|||
import org.geometerplus.zlibrary.core.constants.XMLNamespaces;
|
||||
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
|
||||
|
||||
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
@ -262,12 +264,26 @@ class XMLSerializer extends AbstractSerializer {
|
|||
"access-count", String.valueOf(bookmark.getAccessCount())
|
||||
);
|
||||
appendTag(
|
||||
buffer, "position", true,
|
||||
buffer, "start", true,
|
||||
"model", bookmark.ModelId,
|
||||
"paragraph", String.valueOf(bookmark.getParagraphIndex()),
|
||||
"element", String.valueOf(bookmark.getElementIndex()),
|
||||
"char", String.valueOf(bookmark.getCharIndex())
|
||||
);
|
||||
final ZLTextPosition end = bookmark.getEnd();
|
||||
if (end != null) {
|
||||
appendTag(
|
||||
buffer, "end", true,
|
||||
"paragraph", String.valueOf(end.getParagraphIndex()),
|
||||
"element", String.valueOf(end.getElementIndex()),
|
||||
"char", String.valueOf(end.getCharIndex())
|
||||
);
|
||||
} else {
|
||||
appendTag(
|
||||
buffer, "end", true,
|
||||
"length", String.valueOf(bookmark.getLength())
|
||||
);
|
||||
}
|
||||
closeTag(buffer, "bookmark");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
@ -761,9 +777,12 @@ class XMLSerializer extends AbstractSerializer {
|
|||
private Date myAccessDate;
|
||||
private int myAccessCount;
|
||||
private String myModelId;
|
||||
private int myParagraphIndex;
|
||||
private int myElementIndex;
|
||||
private int myCharIndex;
|
||||
private int myStartParagraphIndex;
|
||||
private int myStartElementIndex;
|
||||
private int myStartCharIndex;
|
||||
private int myEndParagraphIndex;
|
||||
private int myEndElementIndex;
|
||||
private int myEndCharIndex;
|
||||
private boolean myIsVisible;
|
||||
|
||||
public Bookmark getBookmark() {
|
||||
|
@ -783,9 +802,12 @@ class XMLSerializer extends AbstractSerializer {
|
|||
myAccessDate = null;
|
||||
myAccessCount = 0;
|
||||
myModelId = null;
|
||||
myParagraphIndex = 0;
|
||||
myElementIndex = 0;
|
||||
myCharIndex = 0;
|
||||
myStartParagraphIndex = 0;
|
||||
myStartElementIndex = 0;
|
||||
myStartCharIndex = 0;
|
||||
myEndParagraphIndex = -1;
|
||||
myEndElementIndex = -1;
|
||||
myEndCharIndex = -1;
|
||||
myIsVisible = false;
|
||||
|
||||
myState = State.READ_NOTHING;
|
||||
|
@ -799,11 +821,13 @@ class XMLSerializer extends AbstractSerializer {
|
|||
myBookmark = new Bookmark(
|
||||
myId, myBookId, myBookTitle, myText.toString(),
|
||||
myCreationDate, myModificationDate, myAccessDate, myAccessCount,
|
||||
myModelId, myParagraphIndex, myElementIndex, myCharIndex, myIsVisible
|
||||
myModelId,
|
||||
myStartParagraphIndex, myStartElementIndex, myStartCharIndex,
|
||||
myEndParagraphIndex, myEndElementIndex, myEndCharIndex,
|
||||
myIsVisible
|
||||
);
|
||||
}
|
||||
|
||||
//appendTagWithContent(buffer, "text", bookmark.getText());
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
switch (myState) {
|
||||
|
@ -838,12 +862,27 @@ class XMLSerializer extends AbstractSerializer {
|
|||
} catch (Exception e) {
|
||||
throw new SAXException("XML parsing error", e);
|
||||
}
|
||||
} else if ("position".equals(localName)) {
|
||||
} else if ("start".equals(localName)) {
|
||||
try {
|
||||
myModelId = attributes.getValue("model");
|
||||
myParagraphIndex = Integer.parseInt(attributes.getValue("paragraph"));
|
||||
myElementIndex = Integer.parseInt(attributes.getValue("element"));
|
||||
myCharIndex = Integer.parseInt(attributes.getValue("char"));
|
||||
myStartParagraphIndex = Integer.parseInt(attributes.getValue("paragraph"));
|
||||
myStartElementIndex = Integer.parseInt(attributes.getValue("element"));
|
||||
myStartCharIndex = Integer.parseInt(attributes.getValue("char"));
|
||||
} catch (Exception e) {
|
||||
throw new SAXException("XML parsing error", e);
|
||||
}
|
||||
} else if ("end".equals(localName)) {
|
||||
try {
|
||||
final String para = attributes.getValue("paragraph");
|
||||
if (para != null) {
|
||||
myEndParagraphIndex = Integer.parseInt(para);
|
||||
myEndElementIndex = Integer.parseInt(attributes.getValue("element"));
|
||||
myEndCharIndex = Integer.parseInt(attributes.getValue("char"));
|
||||
} else {
|
||||
myEndParagraphIndex = Integer.parseInt(attributes.getValue("length"));
|
||||
myEndElementIndex = -1;
|
||||
myEndCharIndex = -1;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SAXException("XML parsing error", e);
|
||||
}
|
||||
|
|
|
@ -478,7 +478,7 @@ public final class FBReaderApp extends ZLApplication {
|
|||
|
||||
public void addInvisibleBookmark(ZLTextWordCursor cursor) {
|
||||
if (cursor != null && Model != null && Model.Book != null && getTextView() == BookTextView) {
|
||||
updateInvisibleBookmarksList(new Bookmark(
|
||||
updateInvisibleBookmarksList(Bookmark.createBookmark(
|
||||
Model.Book,
|
||||
getTextView().getModel().getId(),
|
||||
cursor,
|
||||
|
@ -502,7 +502,7 @@ public final class FBReaderApp extends ZLApplication {
|
|||
return null;
|
||||
}
|
||||
|
||||
return new Bookmark(
|
||||
return Bookmark.createBookmark(
|
||||
Model.Book,
|
||||
view.getModel().getId(),
|
||||
cursor,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue