1
0
Fork 0
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:
Nikolay Pultsin 2013-04-30 00:26:44 +02:00
parent 7f5257d2fc
commit bc3f86c3fe
6 changed files with 213 additions and 109 deletions

View file

@ -646,6 +646,7 @@ public final class FBReader extends Activity {
myFBReaderApp.Model.Book, myFBReaderApp.Model.Book,
fbView.getModel().getId(), fbView.getModel().getId(),
fbView.getSelectionStartPosition(), fbView.getSelectionStartPosition(),
fbView.getSelectionEndPosition(),
text, text,
true true
); );

View file

@ -839,7 +839,8 @@ final class SQLiteBooksDatabase extends BooksDatabase {
final StringBuilder sql = new StringBuilder("SELECT") final StringBuilder sql = new StringBuilder("SELECT")
.append(" bm.bookmark_id,bm.book_id,b.title,bm.bookmark_text,") .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.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(" FROM Bookmarks AS bm INNER JOIN Books AS b ON b.book_id = bm.book_id")
.append(" WHERE"); .append(" WHERE");
if (query.Book != null) { if (query.Book != null) {
@ -864,7 +865,10 @@ final class SQLiteBooksDatabase extends BooksDatabase {
(int)cursor.getLong(9), (int)cursor.getLong(9),
(int)cursor.getLong(10), (int)cursor.getLong(10),
(int)cursor.getLong(11), (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(); cursor.close();

View file

@ -40,12 +40,21 @@ public final class Bookmark extends ZLTextFixedPosition {
private Date myAccessDate; private Date myAccessDate;
private int myAccessCount; private int myAccessCount;
private Date myLatestDate; private Date myLatestDate;
private ZLTextFixedPosition myEnd;
private int myLength;
public final String ModelId; public final String ModelId;
public final boolean IsVisible; 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) { Bookmark(
super(paragraphIndex, elementIndex, charIndex); 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; myId = id;
myBookId = bookId; myBookId = bookId;
@ -63,14 +72,128 @@ public final class Bookmark extends ZLTextFixedPosition {
myAccessCount = accessCount; myAccessCount = accessCount;
ModelId = modelId; ModelId = modelId;
IsVisible = isVisible; 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) { public Bookmark(Book book, String modelId, ZLTextWordCursor cursor, int maxLength, boolean isVisible) {
this(book, modelId, cursor, createBookmarkText(cursor, maxLength), isVisible); this(book, modelId, cursor, createBookmarkText(cursor, maxLength), isVisible);
} }
*/
public Bookmark(Book book, String modelId, ZLTextPosition position, String text, boolean isVisible) { public Bookmark(Book book, String modelId, ZLTextPosition start, ZLTextPosition end, String text, boolean isVisible) {
super(position); super(start);
myId = -1; myId = -1;
myBookId = book.getId(); myBookId = book.getId();
@ -79,6 +202,7 @@ public final class Bookmark extends ZLTextFixedPosition {
myCreationDate = new Date(); myCreationDate = new Date();
ModelId = modelId; ModelId = modelId;
IsVisible = isVisible; IsVisible = isVisible;
myEnd = new ZLTextFixedPosition(end);
} }
public long getId() { public long getId() {
@ -115,6 +239,14 @@ public final class Bookmark extends ZLTextFixedPosition {
return myAccessCount; return myAccessCount;
} }
public ZLTextPosition getEnd() {
return myEnd;
}
public int getLength() {
return myLength;
}
public void setText(String text) { public void setText(String text) {
if (!text.equals(myText)) { if (!text.equals(myText)) {
myText = text; 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) { void setId(long id) {
myId = id; myId = id;
} }

View file

@ -86,8 +86,22 @@ public abstract class BooksDatabase {
protected abstract void setLabel(long bookId, String label); protected abstract void setLabel(long bookId, String label);
protected abstract void removeLabel(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) { protected Bookmark createBookmark(
return new Bookmark(id, bookId, bookTitle, text, creationDate, modificationDate, accessDate, accessCounter, modelId, paragraphIndex, wordIndex, charIndex, isVisible); 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); protected abstract List<Bookmark> loadBookmarks(BookmarkQuery query);

View file

@ -26,6 +26,8 @@ import java.text.ParseException;
import org.geometerplus.zlibrary.core.constants.XMLNamespaces; import org.geometerplus.zlibrary.core.constants.XMLNamespaces;
import org.geometerplus.zlibrary.core.filesystem.ZLFile; import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.text.view.ZLTextPosition;
import org.xml.sax.Attributes; import org.xml.sax.Attributes;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.DefaultHandler;
@ -262,12 +264,26 @@ class XMLSerializer extends AbstractSerializer {
"access-count", String.valueOf(bookmark.getAccessCount()) "access-count", String.valueOf(bookmark.getAccessCount())
); );
appendTag( appendTag(
buffer, "position", true, buffer, "start", true,
"model", bookmark.ModelId, "model", bookmark.ModelId,
"paragraph", String.valueOf(bookmark.getParagraphIndex()), "paragraph", String.valueOf(bookmark.getParagraphIndex()),
"element", String.valueOf(bookmark.getElementIndex()), "element", String.valueOf(bookmark.getElementIndex()),
"char", String.valueOf(bookmark.getCharIndex()) "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"); closeTag(buffer, "bookmark");
return buffer.toString(); return buffer.toString();
} }
@ -761,9 +777,12 @@ class XMLSerializer extends AbstractSerializer {
private Date myAccessDate; private Date myAccessDate;
private int myAccessCount; private int myAccessCount;
private String myModelId; private String myModelId;
private int myParagraphIndex; private int myStartParagraphIndex;
private int myElementIndex; private int myStartElementIndex;
private int myCharIndex; private int myStartCharIndex;
private int myEndParagraphIndex;
private int myEndElementIndex;
private int myEndCharIndex;
private boolean myIsVisible; private boolean myIsVisible;
public Bookmark getBookmark() { public Bookmark getBookmark() {
@ -783,9 +802,12 @@ class XMLSerializer extends AbstractSerializer {
myAccessDate = null; myAccessDate = null;
myAccessCount = 0; myAccessCount = 0;
myModelId = null; myModelId = null;
myParagraphIndex = 0; myStartParagraphIndex = 0;
myElementIndex = 0; myStartElementIndex = 0;
myCharIndex = 0; myStartCharIndex = 0;
myEndParagraphIndex = -1;
myEndElementIndex = -1;
myEndCharIndex = -1;
myIsVisible = false; myIsVisible = false;
myState = State.READ_NOTHING; myState = State.READ_NOTHING;
@ -799,11 +821,13 @@ class XMLSerializer extends AbstractSerializer {
myBookmark = new Bookmark( myBookmark = new Bookmark(
myId, myBookId, myBookTitle, myText.toString(), myId, myBookId, myBookTitle, myText.toString(),
myCreationDate, myModificationDate, myAccessDate, myAccessCount, myCreationDate, myModificationDate, myAccessDate, myAccessCount,
myModelId, myParagraphIndex, myElementIndex, myCharIndex, myIsVisible myModelId,
myStartParagraphIndex, myStartElementIndex, myStartCharIndex,
myEndParagraphIndex, myEndElementIndex, myEndCharIndex,
myIsVisible
); );
} }
//appendTagWithContent(buffer, "text", bookmark.getText());
@Override @Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (myState) { switch (myState) {
@ -838,12 +862,27 @@ class XMLSerializer extends AbstractSerializer {
} catch (Exception e) { } catch (Exception e) {
throw new SAXException("XML parsing error", e); throw new SAXException("XML parsing error", e);
} }
} else if ("position".equals(localName)) { } else if ("start".equals(localName)) {
try { try {
myModelId = attributes.getValue("model"); myModelId = attributes.getValue("model");
myParagraphIndex = Integer.parseInt(attributes.getValue("paragraph")); myStartParagraphIndex = Integer.parseInt(attributes.getValue("paragraph"));
myElementIndex = Integer.parseInt(attributes.getValue("element")); myStartElementIndex = Integer.parseInt(attributes.getValue("element"));
myCharIndex = Integer.parseInt(attributes.getValue("char")); 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) { } catch (Exception e) {
throw new SAXException("XML parsing error", e); throw new SAXException("XML parsing error", e);
} }

View file

@ -478,7 +478,7 @@ public final class FBReaderApp extends ZLApplication {
public void addInvisibleBookmark(ZLTextWordCursor cursor) { public void addInvisibleBookmark(ZLTextWordCursor cursor) {
if (cursor != null && Model != null && Model.Book != null && getTextView() == BookTextView) { if (cursor != null && Model != null && Model.Book != null && getTextView() == BookTextView) {
updateInvisibleBookmarksList(new Bookmark( updateInvisibleBookmarksList(Bookmark.createBookmark(
Model.Book, Model.Book,
getTextView().getModel().getId(), getTextView().getModel().getId(),
cursor, cursor,
@ -502,7 +502,7 @@ public final class FBReaderApp extends ZLApplication {
return null; return null;
} }
return new Bookmark( return Bookmark.createBookmark(
Model.Book, Model.Book,
view.getModel().getId(), view.getModel().getId(),
cursor, cursor,