mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 02:39:23 +02:00
TagTree on-the-fly
This commit is contained in:
parent
4e95e802a2
commit
147236cce3
14 changed files with 231 additions and 75 deletions
|
@ -134,6 +134,19 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized List<Book> books(Tag tag) {
|
||||||
|
if (myInterface == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return SerializerUtil.deserializeBookList(
|
||||||
|
myInterface.booksForTag(Util.tagToString(tag))
|
||||||
|
);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized List<Book> books(String pattern) {
|
public synchronized List<Book> books(String pattern) {
|
||||||
if (myInterface == null) {
|
if (myInterface == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -220,12 +233,16 @@ public class BookCollectionShadow extends AbstractBookCollection implements Serv
|
||||||
if (myInterface == null) {
|
if (myInterface == null) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
//try {
|
try {
|
||||||
// TODO: implement
|
final List<String> strings = myInterface.tags();
|
||||||
|
final List<Tag> tags = new ArrayList<Tag>(strings.size());
|
||||||
|
for (String s : strings) {
|
||||||
|
tags.add(Util.stringToTag(s));
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
} catch (RemoteException e) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
//} catch (RemoteException e) {
|
}
|
||||||
// return Collections.emptyList();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized List<String> series() {
|
public synchronized List<String> series() {
|
||||||
|
|
|
@ -11,6 +11,7 @@ interface LibraryInterface {
|
||||||
int size();
|
int size();
|
||||||
List<String> books();
|
List<String> books();
|
||||||
List<String> booksForAuthor(in String author);
|
List<String> booksForAuthor(in String author);
|
||||||
|
List<String> booksForTag(in String tag);
|
||||||
List<String> booksForPattern(in String pattern);
|
List<String> booksForPattern(in String pattern);
|
||||||
List<String> recentBooks();
|
List<String> recentBooks();
|
||||||
List<String> favorites();
|
List<String> favorites();
|
||||||
|
@ -19,6 +20,8 @@ interface LibraryInterface {
|
||||||
String getRecentBook(in int index);
|
String getRecentBook(in int index);
|
||||||
|
|
||||||
List<String> authors();
|
List<String> authors();
|
||||||
|
List<String> series();
|
||||||
|
List<String> tags();
|
||||||
|
|
||||||
boolean saveBook(in String book, in boolean force);
|
boolean saveBook(in String book, in boolean force);
|
||||||
void removeBook(in String book, in boolean deleteFromDisk);
|
void removeBook(in String book, in boolean deleteFromDisk);
|
||||||
|
|
|
@ -123,6 +123,10 @@ public class LibraryService extends Service {
|
||||||
return SerializerUtil.serializeBookList(myCollection.books(Util.stringToAuthor(author)));
|
return SerializerUtil.serializeBookList(myCollection.books(Util.stringToAuthor(author)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> booksForTag(String tag) {
|
||||||
|
return SerializerUtil.serializeBookList(myCollection.books(Util.stringToTag(tag)));
|
||||||
|
}
|
||||||
|
|
||||||
public List<String> booksForPattern(String pattern) {
|
public List<String> booksForPattern(String pattern) {
|
||||||
return SerializerUtil.serializeBookList(myCollection.books(pattern));
|
return SerializerUtil.serializeBookList(myCollection.books(pattern));
|
||||||
}
|
}
|
||||||
|
@ -156,6 +160,19 @@ public class LibraryService extends Service {
|
||||||
return strings;
|
return strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> series() {
|
||||||
|
return myCollection.series();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> tags() {
|
||||||
|
final List<Tag> tags = myCollection.tags();
|
||||||
|
final List<String> strings = new ArrayList<String>(tags.size());
|
||||||
|
for (Tag t : tags) {
|
||||||
|
strings.add(Util.tagToString(t));
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean saveBook(String book, boolean force) {
|
public boolean saveBook(String book, boolean force) {
|
||||||
return myCollection.saveBook(SerializerUtil.deserializeBook(book), force);
|
return myCollection.saveBook(SerializerUtil.deserializeBook(book), force);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.geometerplus.android.fbreader.libraryService;
|
package org.geometerplus.android.fbreader.libraryService;
|
||||||
|
|
||||||
import org.geometerplus.fbreader.book.Author;
|
import org.geometerplus.fbreader.book.Author;
|
||||||
|
import org.geometerplus.fbreader.book.Tag;
|
||||||
|
|
||||||
abstract class Util {
|
abstract class Util {
|
||||||
static String authorToString(Author author) {
|
static String authorToString(Author author) {
|
||||||
|
@ -34,4 +35,17 @@ abstract class Util {
|
||||||
return Author.NULL;
|
return Author.NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static String tagToString(Tag tag) {
|
||||||
|
return tag.toString("\000");
|
||||||
|
}
|
||||||
|
|
||||||
|
static Tag stringToTag(String string) {
|
||||||
|
final String[] splitted = string.split("\000");
|
||||||
|
if (splitted.length > 0) {
|
||||||
|
return Tag.getTag(splitted);
|
||||||
|
} else {
|
||||||
|
return Tag.NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,18 @@ public class BookCollection extends AbstractBookCollection {
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Book> books(Tag tag) {
|
||||||
|
final boolean isNull = Tag.NULL.equals(tag);
|
||||||
|
final LinkedList<Book> filtered = new LinkedList<Book>();
|
||||||
|
for (Book b : books()) {
|
||||||
|
final List<Tag> bookTags = b.tags();
|
||||||
|
if (isNull && bookTags.isEmpty() || bookTags.contains(tag)) {
|
||||||
|
filtered.add(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Book> books(String pattern) {
|
public List<Book> books(String pattern) {
|
||||||
if (pattern == null || pattern.length() == 0) {
|
if (pattern == null || pattern.length() == 0) {
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
@ -262,9 +274,14 @@ public class BookCollection extends AbstractBookCollection {
|
||||||
final Set<Tag> tags = new TreeSet<Tag>();
|
final Set<Tag> tags = new TreeSet<Tag>();
|
||||||
synchronized (myBooksByFile) {
|
synchronized (myBooksByFile) {
|
||||||
for (Book book : myBooksByFile.values()) {
|
for (Book book : myBooksByFile.values()) {
|
||||||
|
final List<Tag> bookTags = book.tags();
|
||||||
|
if (bookTags.isEmpty()) {
|
||||||
|
tags.add(Tag.NULL);
|
||||||
|
} else {
|
||||||
tags.addAll(book.tags());
|
tags.addAll(book.tags());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new ArrayList<Tag>(tags);
|
return new ArrayList<Tag>(tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ public interface IBookCollection {
|
||||||
int size();
|
int size();
|
||||||
List<Book> books();
|
List<Book> books();
|
||||||
List<Book> books(Author author);
|
List<Book> books(Author author);
|
||||||
|
List<Book> books(Tag tag);
|
||||||
List<Book> books(String pattern);
|
List<Book> books(String pattern);
|
||||||
List<Book> recentBooks();
|
List<Book> recentBooks();
|
||||||
List<Book> favorites();
|
List<Book> favorites();
|
||||||
|
|
|
@ -22,6 +22,8 @@ package org.geometerplus.fbreader.book;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
public final class Tag {
|
public final class Tag {
|
||||||
|
public static final Tag NULL = new Tag(null, "");
|
||||||
|
|
||||||
private static final HashMap<Tag,Tag> ourTagSet = new HashMap<Tag,Tag>();
|
private static final HashMap<Tag,Tag> ourTagSet = new HashMap<Tag,Tag>();
|
||||||
|
|
||||||
public static Tag getTag(Tag parent, String name) {
|
public static Tag getTag(Tag parent, String name) {
|
||||||
|
|
|
@ -45,14 +45,13 @@ public class AuthorListTree extends FirstLevelTree {
|
||||||
@Override
|
@Override
|
||||||
public boolean onBookEvent(BookEvent event, Book book) {
|
public boolean onBookEvent(BookEvent event, Book book) {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
default:
|
|
||||||
case Added:
|
case Added:
|
||||||
{
|
{
|
||||||
final List<Author> bookAuthors = book.authors();
|
final List<Author> bookAuthors = book.authors();
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
if (bookAuthors.isEmpty()) {
|
if (bookAuthors.isEmpty()) {
|
||||||
changed &= createAuthorSubTree(Author.NULL);
|
changed &= createAuthorSubTree(Author.NULL);
|
||||||
} else for (Author a : Collection.authors()) {
|
} else for (Author a : bookAuthors) {
|
||||||
changed &= createAuthorSubTree(a);
|
changed &= createAuthorSubTree(a);
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
@ -60,6 +59,7 @@ public class AuthorListTree extends FirstLevelTree {
|
||||||
case Removed:
|
case Removed:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return false;
|
return false;
|
||||||
|
default:
|
||||||
case Updated:
|
case Updated:
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -39,10 +39,8 @@ public class AuthorTree extends LibraryTree {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return
|
return Author.NULL.equals(Author)
|
||||||
Author != Author.NULL ?
|
? Library.resource().getResource("unknownAuthor").getValue() : Author.DisplayName;
|
||||||
Author.DisplayName :
|
|
||||||
Library.resource().getResource("unknownAuthor").getValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,7 +50,7 @@ public class AuthorTree extends LibraryTree {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getSortKey() {
|
protected String getSortKey() {
|
||||||
if (Author == null) {
|
if (Author.NULL.equals(Author)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new StringBuilder()
|
return new StringBuilder()
|
||||||
|
@ -90,12 +88,16 @@ public class AuthorTree extends LibraryTree {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case Added:
|
case Added:
|
||||||
return containsBook(book) && createBookSubTree(book);
|
return containsBook(book) && createBookSubTree(book);
|
||||||
|
case Removed:
|
||||||
|
// TODO: implement
|
||||||
|
case Updated:
|
||||||
|
// TODO: implement
|
||||||
default:
|
default:
|
||||||
return super.onBookEvent(event, book);
|
return super.onBookEvent(event, book);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean createBookSubTree(Book book) {
|
private boolean createBookSubTree(Book book) {
|
||||||
final SeriesInfo seriesInfo = book.getSeriesInfo();
|
final SeriesInfo seriesInfo = book.getSeriesInfo();
|
||||||
if (seriesInfo != null) {
|
if (seriesInfo != null) {
|
||||||
return getSeriesSubTree(seriesInfo.Title).createBookInSeriesSubTree(book);
|
return getSeriesSubTree(seriesInfo.Title).createBookInSeriesSubTree(book);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class FavoritesTree extends FirstLevelTree {
|
||||||
new BookWithAuthorsTree(this, book);
|
new BookWithAuthorsTree(this, book);
|
||||||
return true;
|
return true;
|
||||||
} if (event == BookEvent.Updated && !Collection.isFavorite(book)) {
|
} if (event == BookEvent.Updated && !Collection.isFavorite(book)) {
|
||||||
return removeBook(book, false);
|
return removeBook(book);
|
||||||
} else {
|
} else {
|
||||||
return super.onBookEvent(event, book);
|
return super.onBookEvent(event, book);
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ public final class Library {
|
||||||
new RecentBooksTree(myRootTree);
|
new RecentBooksTree(myRootTree);
|
||||||
new AuthorListTree(myRootTree);
|
new AuthorListTree(myRootTree);
|
||||||
new FirstLevelTree(myRootTree, LibraryTree.ROOT_BY_TITLE);
|
new FirstLevelTree(myRootTree, LibraryTree.ROOT_BY_TITLE);
|
||||||
new FirstLevelTree(myRootTree, LibraryTree.ROOT_BY_TAG);
|
new TagListTree(myRootTree);
|
||||||
new FileFirstLevelTree(myRootTree);
|
new FileFirstLevelTree(myRootTree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,26 +224,12 @@ public final class Library {
|
||||||
return fileList;
|
return fileList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<?> myNullList = Collections.singletonList(null);
|
|
||||||
|
|
||||||
private LibraryTree getTagTree(Tag tag) {
|
|
||||||
if (tag == null || tag.Parent == null) {
|
|
||||||
return getFirstLevelTree(LibraryTree.ROOT_BY_TAG).getTagSubTree(tag);
|
|
||||||
} else {
|
|
||||||
return getTagTree(tag.Parent).getTagSubTree(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void addBookToLibrary(Book book) {
|
private synchronized void addBookToLibrary(Book book) {
|
||||||
if (myBooks.containsKey(book.File)) {
|
if (myBooks.containsKey(book.File)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
myBooks.put(book.File, book);
|
myBooks.put(book.File, book);
|
||||||
|
|
||||||
List<Author> authors = book.authors();
|
|
||||||
if (authors.isEmpty()) {
|
|
||||||
authors = (List<Author>)myNullList;
|
|
||||||
}
|
|
||||||
final SeriesInfo seriesInfo = book.getSeriesInfo();
|
final SeriesInfo seriesInfo = book.getSeriesInfo();
|
||||||
|
|
||||||
if (seriesInfo != null) {
|
if (seriesInfo != null) {
|
||||||
|
@ -263,42 +249,23 @@ public final class Library {
|
||||||
if (letter != null) {
|
if (letter != null) {
|
||||||
final TitleTree tree =
|
final TitleTree tree =
|
||||||
getFirstLevelTree(LibraryTree.ROOT_BY_TITLE).getTitleSubTree(letter);
|
getFirstLevelTree(LibraryTree.ROOT_BY_TITLE).getTitleSubTree(letter);
|
||||||
tree.getBookWithAuthorsSubTree(book);
|
tree.createBookWithAuthorsSubTree(book);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getFirstLevelTree(LibraryTree.ROOT_BY_TITLE).getBookWithAuthorsSubTree(book);
|
getFirstLevelTree(LibraryTree.ROOT_BY_TITLE).createBookWithAuthorsSubTree(book);
|
||||||
}
|
|
||||||
|
|
||||||
List<Tag> tags = book.tags();
|
|
||||||
if (tags.isEmpty()) {
|
|
||||||
tags = (List<Tag>)myNullList;
|
|
||||||
}
|
|
||||||
for (Tag t : tags) {
|
|
||||||
getTagTree(t).getBookWithAuthorsSubTree(book);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final SearchResultsTree found =
|
final SearchResultsTree found =
|
||||||
(SearchResultsTree)getFirstLevelTree(LibraryTree.ROOT_FOUND);
|
(SearchResultsTree)getFirstLevelTree(LibraryTree.ROOT_FOUND);
|
||||||
if (found != null && book.matches(found.getPattern())) {
|
if (found != null && book.matches(found.getPattern())) {
|
||||||
found.getBookWithAuthorsSubTree(book);
|
found.createBookWithAuthorsSubTree(book);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeFromTree(String rootId, Book book) {
|
private void removeFromTree(String rootId, Book book) {
|
||||||
final FirstLevelTree tree = getFirstLevelTree(rootId);
|
final FirstLevelTree tree = getFirstLevelTree(rootId);
|
||||||
if (tree != null) {
|
if (tree != null) {
|
||||||
tree.removeBook(book, false);
|
tree.removeBook(book);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshInTree(String rootId, Book book) {
|
|
||||||
final FirstLevelTree tree = getFirstLevelTree(rootId);
|
|
||||||
if (tree != null) {
|
|
||||||
int index = tree.indexOf(new BookWithAuthorsTree(Collection, book));
|
|
||||||
if (index >= 0) {
|
|
||||||
tree.removeBook(book, false);
|
|
||||||
new BookWithAuthorsTree(tree, book, index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +278,6 @@ public final class Library {
|
||||||
removeFromTree(LibraryTree.ROOT_FOUND, book);
|
removeFromTree(LibraryTree.ROOT_FOUND, book);
|
||||||
removeFromTree(LibraryTree.ROOT_BY_TITLE, book);
|
removeFromTree(LibraryTree.ROOT_BY_TITLE, book);
|
||||||
removeFromTree(LibraryTree.ROOT_BY_SERIES, book);
|
removeFromTree(LibraryTree.ROOT_BY_SERIES, book);
|
||||||
removeFromTree(LibraryTree.ROOT_BY_TAG, book);
|
|
||||||
addBookToLibrary(book);
|
addBookToLibrary(book);
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
||||||
}
|
}
|
||||||
|
@ -377,7 +343,6 @@ public final class Library {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
myRootTree.removeBook(book, true);
|
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookRemoved);
|
fireModelChangedEvent(ChangeListener.Code.BookRemoved);
|
||||||
orphanedBooks.add(book);
|
orphanedBooks.add(book);
|
||||||
}
|
}
|
||||||
|
@ -511,7 +476,7 @@ public final class Library {
|
||||||
newSearchResults = new SearchResultsTree(myRootTree, LibraryTree.ROOT_FOUND, pattern);
|
newSearchResults = new SearchResultsTree(myRootTree, LibraryTree.ROOT_FOUND, pattern);
|
||||||
fireModelChangedEvent(ChangeListener.Code.Found);
|
fireModelChangedEvent(ChangeListener.Code.Found);
|
||||||
}
|
}
|
||||||
newSearchResults.getBookWithAuthorsSubTree(book);
|
newSearchResults.createBookWithAuthorsSubTree(book);
|
||||||
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
fireModelChangedEvent(ChangeListener.Code.BookAdded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,7 +510,6 @@ public final class Library {
|
||||||
}
|
}
|
||||||
myBooks.remove(book.File);
|
myBooks.remove(book.File);
|
||||||
Collection.removeBook(book, (removeMode & REMOVE_FROM_DISK) != 0);
|
Collection.removeBook(book, (removeMode & REMOVE_FROM_DISK) != 0);
|
||||||
myRootTree.removeBook(book, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Bookmark> allBookmarks() {
|
public List<Bookmark> allBookmarks() {
|
||||||
|
|
|
@ -63,13 +63,14 @@ public abstract class LibraryTree extends FBTree {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagTree getTagSubTree(Tag tag) {
|
boolean createTagSubTree(Tag tag) {
|
||||||
final TagTree temp = new TagTree(Collection, tag);
|
final TagTree temp = new TagTree(Collection, tag);
|
||||||
int position = Collections.binarySearch(subTrees(), temp);
|
int position = Collections.binarySearch(subTrees(), temp);
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
return (TagTree)subTrees().get(position);
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return new TagTree(this, tag, - position - 1);
|
new TagTree(this, tag, - position - 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,13 +84,14 @@ public abstract class LibraryTree extends FBTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BookWithAuthorsTree getBookWithAuthorsSubTree(Book book) {
|
boolean createBookWithAuthorsSubTree(Book book) {
|
||||||
final BookWithAuthorsTree temp = new BookWithAuthorsTree(Collection, book);
|
final BookWithAuthorsTree temp = new BookWithAuthorsTree(Collection, book);
|
||||||
int position = Collections.binarySearch(subTrees(), temp);
|
int position = Collections.binarySearch(subTrees(), temp);
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
return (BookWithAuthorsTree)subTrees().get(position);
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return new BookWithAuthorsTree(this, book, - position - 1);
|
new BookWithAuthorsTree(this, book, - position - 1);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ public abstract class LibraryTree extends FBTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeBook(Book book, boolean recursively) {
|
public boolean removeBook(Book book) {
|
||||||
final LinkedList<FBTree> toRemove = new LinkedList<FBTree>();
|
final LinkedList<FBTree> toRemove = new LinkedList<FBTree>();
|
||||||
for (FBTree tree : this) {
|
for (FBTree tree : this) {
|
||||||
if (tree instanceof BookTree && ((BookTree)tree).Book.equals(book)) {
|
if (tree instanceof BookTree && ((BookTree)tree).Book.equals(book)) {
|
||||||
|
@ -112,12 +114,6 @@ public abstract class LibraryTree extends FBTree {
|
||||||
}
|
}
|
||||||
for (FBTree tree : toRemove) {
|
for (FBTree tree : toRemove) {
|
||||||
tree.removeSelf();
|
tree.removeSelf();
|
||||||
FBTree parent = tree.Parent;
|
|
||||||
if (recursively) {
|
|
||||||
for (; parent != null && !parent.hasChildren(); parent = parent.Parent) {
|
|
||||||
parent.removeSelf();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return !toRemove.isEmpty();
|
return !toRemove.isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -128,7 +124,7 @@ public abstract class LibraryTree extends FBTree {
|
||||||
case Added:
|
case Added:
|
||||||
return false;
|
return false;
|
||||||
case Removed:
|
case Removed:
|
||||||
return removeBook(book, true);
|
return removeBook(book);
|
||||||
case Updated:
|
case Updated:
|
||||||
{
|
{
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
72
src/org/geometerplus/fbreader/library/TagListTree.java
Normal file
72
src/org/geometerplus/fbreader/library/TagListTree.java
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2013 Geometer Plus <contact@geometerplus.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geometerplus.fbreader.library;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.geometerplus.fbreader.book.*;
|
||||||
|
|
||||||
|
public class TagListTree extends FirstLevelTree {
|
||||||
|
TagListTree(RootTree root) {
|
||||||
|
super(root, ROOT_BY_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status getOpeningStatus() {
|
||||||
|
return Status.ALWAYS_RELOAD_BEFORE_OPENING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void waitForOpening() {
|
||||||
|
clear();
|
||||||
|
for (Tag t : Collection.tags()) {
|
||||||
|
if (t.Parent == null) {
|
||||||
|
createTagSubTree(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onBookEvent(BookEvent event, Book book) {
|
||||||
|
switch (event) {
|
||||||
|
case Added:
|
||||||
|
{
|
||||||
|
final List<Tag> bookTags = book.tags();
|
||||||
|
boolean changed = false;
|
||||||
|
if (bookTags.isEmpty()) {
|
||||||
|
changed &= createTagSubTree(Tag.NULL);
|
||||||
|
} else for (Tag t : bookTags) {
|
||||||
|
if (t.Parent == null) {
|
||||||
|
changed &= createTagSubTree(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
case Removed:
|
||||||
|
// TODO: implement
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
case Updated:
|
||||||
|
// TODO: implement
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
package org.geometerplus.fbreader.library;
|
package org.geometerplus.fbreader.library;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.geometerplus.fbreader.book.*;
|
import org.geometerplus.fbreader.book.*;
|
||||||
|
|
||||||
public final class TagTree extends LibraryTree {
|
public final class TagTree extends LibraryTree {
|
||||||
|
@ -36,8 +38,8 @@ public final class TagTree extends LibraryTree {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return Tag != null
|
return Tag.NULL.equals(Tag)
|
||||||
? Tag.Name : Library.resource().getResource("booksWithNoTags").getValue();
|
? Library.resource().getResource("booksWithNoTags").getValue() : Tag.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -46,7 +48,7 @@ public final class TagTree extends LibraryTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getSortKey() {
|
protected String getSortKey() {
|
||||||
return Tag != null ? Tag.Name : null;
|
return Tag.NULL.equals(Tag) ? null : Tag.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -54,7 +56,7 @@ public final class TagTree extends LibraryTree {
|
||||||
if (book == null) {
|
if (book == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Tag == null) {
|
if (Tag.NULL.equals(Tag)) {
|
||||||
return book.tags().isEmpty();
|
return book.tags().isEmpty();
|
||||||
}
|
}
|
||||||
for (Tag t : book.tags()) {
|
for (Tag t : book.tags()) {
|
||||||
|
@ -66,4 +68,53 @@ public final class TagTree extends LibraryTree {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status getOpeningStatus() {
|
||||||
|
return Status.ALWAYS_RELOAD_BEFORE_OPENING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void waitForOpening() {
|
||||||
|
clear();
|
||||||
|
if (!Tag.NULL.equals(Tag)) {
|
||||||
|
for (Tag t : Collection.tags()) {
|
||||||
|
if (Tag.equals(t.Parent)) {
|
||||||
|
createTagSubTree(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Book book : Collection.books(Tag)) {
|
||||||
|
createBookWithAuthorsSubTree(book);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onBookEvent(BookEvent event, Book book) {
|
||||||
|
switch (event) {
|
||||||
|
case Added:
|
||||||
|
{
|
||||||
|
boolean changed = false;
|
||||||
|
final List<Tag> bookTags = book.tags();
|
||||||
|
if (bookTags.isEmpty()) {
|
||||||
|
changed &= Tag.NULL.equals(Tag) && createBookWithAuthorsSubTree(book);
|
||||||
|
} else {
|
||||||
|
for (Tag t : bookTags) {
|
||||||
|
if (Tag.equals(t)) {
|
||||||
|
changed &= createBookWithAuthorsSubTree(book);
|
||||||
|
} else if (Tag.equals(t.Parent)) {
|
||||||
|
changed &= createTagSubTree(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
case Removed:
|
||||||
|
// TODO: implement
|
||||||
|
case Updated:
|
||||||
|
// TODO: implement
|
||||||
|
default:
|
||||||
|
return super.onBookEvent(event, book);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue