diff options
Diffstat (limited to 'fbreader/src/libraryTree')
-rw-r--r-- | fbreader/src/libraryTree/AuthorNode.cpp | 60 | ||||
-rw-r--r-- | fbreader/src/libraryTree/BookNode.cpp | 116 | ||||
-rw-r--r-- | fbreader/src/libraryTree/LibraryByAuthorView.cpp | 173 | ||||
-rw-r--r-- | fbreader/src/libraryTree/LibraryByTagView.cpp | 97 | ||||
-rw-r--r-- | fbreader/src/libraryTree/LibraryNodes.h | 120 | ||||
-rw-r--r-- | fbreader/src/libraryTree/LibraryView.cpp | 86 | ||||
-rw-r--r-- | fbreader/src/libraryTree/LibraryView.h | 86 | ||||
-rw-r--r-- | fbreader/src/libraryTree/SeriesNode.cpp | 61 | ||||
-rw-r--r-- | fbreader/src/libraryTree/TagNode.cpp | 78 |
9 files changed, 877 insertions, 0 deletions
diff --git a/fbreader/src/libraryTree/AuthorNode.cpp b/fbreader/src/libraryTree/AuthorNode.cpp new file mode 100644 index 0000000..a250c1a --- /dev/null +++ b/fbreader/src/libraryTree/AuthorNode.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLResource.h> +#include <ZLImage.h> +#include <ZLOptionsDialog.h> + +#include "LibraryNodes.h" + +#include "../library/Author.h" +#include "../libraryActions/LibraryAuthorActions.h" + +const ZLTypeId AuthorNode::TYPE_ID(FBReaderNode::TYPE_ID); + +const ZLResource &AuthorNode::resource() const { + return ZLResource::resource("libraryView")["authorNode"]; +} + +const ZLTypeId &AuthorNode::typeId() const { + return TYPE_ID; +} + +AuthorNode::AuthorNode(ZLBlockTreeView::RootNode *parent, std::size_t atPosition, shared_ptr<Author> author) : FBReaderNode(parent, atPosition), myAuthor(author) { +} + +void AuthorNode::init() { + registerExpandTreeAction(); + if (!myAuthor.isNull()) { + registerAction(new AuthorEditInfoAction(myAuthor)); + } +} + +shared_ptr<Author> AuthorNode::author() const { + return myAuthor; +} + +std::string AuthorNode::title() const { + return myAuthor.isNull() ? + resource()["unknownAuthor"].value() : myAuthor->name(); +} + +shared_ptr<const ZLImage> AuthorNode::extractCoverImage() const { + return defaultCoverImage("booktree-author.png"); +} diff --git a/fbreader/src/libraryTree/BookNode.cpp b/fbreader/src/libraryTree/BookNode.cpp new file mode 100644 index 0000000..0df43e5 --- /dev/null +++ b/fbreader/src/libraryTree/BookNode.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLResource.h> +#include <ZLImage.h> + +#include "LibraryNodes.h" + +#include "../library/Book.h" +#include "../library/Author.h" +#include "../library/Tag.h" +#include "../libraryActions/LibraryBookActions.h" + +#include "../fbreader/FBReader.h" +#include "../formats/FormatPlugin.h" + +const ZLTypeId BookNode::TYPE_ID(FBReaderNode::TYPE_ID); + +const ZLTypeId &BookNode::typeId() const { + return TYPE_ID; +} + +const ZLResource &BookNode::resource() const { + return ZLResource::resource("libraryView")["bookNode"]; +} + +BookNode::BookNode(AuthorNode *parent, shared_ptr<Book> book) : FBReaderNode(parent), myBook(book) { +} + +BookNode::BookNode(SeriesNode *parent, shared_ptr<Book> book) : FBReaderNode(parent), myBook(book) { +} + +BookNode::BookNode(TagNode *parent, std::size_t atPosition, shared_ptr<Book> book) : FBReaderNode(parent, atPosition), myBook(book) { +} + +void BookNode::init() { + registerAction(new BookReadAction(myBook)); + registerAction(new BookEditInfoAction(myBook)); + registerAction(new BookRemoveAction(myBook)); +} + +shared_ptr<Book> BookNode::book() const { + return myBook; +} + +std::string BookNode::title() const { + return myBook->title(); +} + +std::string BookNode::summary() const { + FBReaderNode *parent = (FBReaderNode*)this->parent(); + while (!parent->isInstanceOf(AuthorNode::TYPE_ID) && + !parent->isInstanceOf(TagNode::TYPE_ID)) { + parent = (FBReaderNode*)parent->parent(); + } + if (parent->isInstanceOf(AuthorNode::TYPE_ID)) { + const TagList &tags = myBook->tags(); + if (tags.empty()) { + return std::string(); + } else { + std::string tagsText; + for (TagList::const_iterator it = tags.begin(); it != tags.end(); ++it) { + if (!tagsText.empty()) { + tagsText += ", "; + } + tagsText += (*it)->name(); + } + return tagsText; + } + } else { + const AuthorList &authors = myBook->authors(); + if (authors.empty()) { + return ZLResource::resource("libraryView")["authorNode"]["unknownAuthor"].value(); + } else { + std::string authorsText; + for (AuthorList::const_iterator it = authors.begin(); it != authors.end(); ++it) { + if (!authorsText.empty()) { + authorsText += ", "; + } + authorsText += (*it)->name(); + } + return authorsText; + } + } +} + +bool BookNode::highlighted() const { + return myBook->file() == FBReader::Instance().currentBook()->file(); +} + +shared_ptr<const ZLImage> BookNode::extractCoverImage() const { + shared_ptr<FormatPlugin> plugin = PluginCollection::Instance().plugin(*myBook); + if (!plugin.isNull()) { + shared_ptr<const ZLImage> cover = plugin->coverImage(myBook->file()); + if (!cover.isNull()) { + return cover; + } + } + return defaultCoverImage("booktree-book.png"); +} diff --git a/fbreader/src/libraryTree/LibraryByAuthorView.cpp b/fbreader/src/libraryTree/LibraryByAuthorView.cpp new file mode 100644 index 0000000..68a13f4 --- /dev/null +++ b/fbreader/src/libraryTree/LibraryByAuthorView.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include "LibraryView.h" +#include "LibraryNodes.h" + +#include "../library/Library.h" +#include "../library/Book.h" +#include "../library/Author.h" + +LibraryByAuthorView::LibraryByAuthorView(ZLPaintContext &context) : LibraryView(context) { +} + +void LibraryByAuthorView::addAuthorSubtree(shared_ptr<Author> author, std::size_t atPosition) { + static const std::set<shared_ptr<Book> > emptySet; + fillAuthorSubtree(new AuthorNode(&rootNode(), atPosition, author), emptySet); +} + +void LibraryByAuthorView::fillAuthorSubtree(AuthorNode *authorNode, const std::set<shared_ptr<Book> > &visibleBooks) { + const BookList &books = Library::Instance().books(authorNode->author()); + SeriesNode *seriesNode = 0; + for (BookList::const_iterator it = books.begin(); it != books.end(); ++it) { + std::string series = (*it)->seriesTitle(); + + if (!series.empty() && (seriesNode == 0 || seriesNode->book()->seriesTitle() != series)) { + BookList::const_iterator jt = it + 1; + if (jt == books.end() || (*jt)->seriesTitle() != series) { + series.clear(); + } + } + + if (series.empty()) { + seriesNode = 0; + new BookNode(authorNode, *it); + } else { + if (seriesNode == 0 || seriesNode->book()->seriesTitle() != series) { + seriesNode = new SeriesNode(authorNode); + } + new BookNode(seriesNode, *it); + if (visibleBooks.find(*it) != visibleBooks.end()) { + seriesNode->open(true); + } + } + } +} + +bool LibraryByAuthorView::isSubtreeUpToDate(AuthorNode *authorNode) { + const BookList &books = Library::Instance().books(authorNode->author()); + BookList::const_iterator it = books.begin(); + + const ZLBlockTreeNode::List &nodes = authorNode->children(); + for (ZLBlockTreeNode::List::const_iterator nIt = nodes.begin(); nIt != nodes.end(); ++nIt) { + FBReaderNode &node = *(FBReaderNode*)*nIt; + if (node.isInstanceOf(BookNode::TYPE_ID)) { + shared_ptr<Book> book = ((BookNode&)node).book(); + if (it == books.end() || *it != book || !book->seriesTitle().empty()) { + return false; + } + ++it; + } else /* if (node.isInstanceOf(SeriesNode::TYPE_ID)) */ { + const ZLBlockTreeNode::List &bNodes = node.children(); + for (ZLBlockTreeNode::List::const_iterator bookIt = bNodes.begin(); bookIt != bNodes.end(); ++bookIt) { + shared_ptr<Book> book = ((BookNode*)*bookIt)->book(); + if (it == books.end() || *it != book || book->seriesTitle().empty()) { + return false; + } + ++it; + } + } + } + return it == books.end(); +} + +void LibraryByAuthorView::updateAuthorSubtree(AuthorNode *authorNode) { + std::set<shared_ptr<Book> > visibleBooks; + + const ZLBlockTreeNode::List &nodes = authorNode->children(); + for (ZLBlockTreeNode::List::const_iterator nIt = nodes.begin(); nIt != nodes.end(); ++nIt) { + FBReaderNode &node = *(FBReaderNode*)*nIt; + if (node.isInstanceOf(BookNode::TYPE_ID)) { + visibleBooks.insert(((BookNode&)node).book()); + } else if (node.isOpen()) { + const ZLBlockTreeNode::List &bNodes = node.children(); + for (ZLBlockTreeNode::List::const_iterator bookIt = bNodes.begin(); bookIt != bNodes.end(); ++bookIt) { + visibleBooks.insert(((BookNode*)*bookIt)->book()); + } + } + } + + authorNode->clear(); + fillAuthorSubtree(authorNode, visibleBooks); +} + +void LibraryByAuthorView::makeUpToDate() { + ZLBlockTreeNode *topNode = firstVisibleNode(); + AuthorNode *topAuthorNode = 0; + if (topNode != &rootNode()) { + FBReaderNode *lNode = (FBReaderNode*)topNode; + while (!lNode->isInstanceOf(AuthorNode::TYPE_ID)) { + lNode = (FBReaderNode*)lNode->parent(); + } + topAuthorNode = (AuthorNode*)lNode; + } + + bool topAuthorNodeIsUpdated = false; + const AuthorList &authors = Library::Instance().authors(); + std::set<ZLBlockTreeNode*> nodesToDelete; + ZLBlockTreeNode::List rootChildren = rootNode().children(); + AuthorComparator comparator; + + ZLBlockTreeNode::List::iterator nodeIt = rootChildren.begin(); + std::size_t nodeCount = 0; + for (AuthorList::const_iterator it = authors.begin(); it != authors.end(); ++it) { + bool processed = false; + while (nodeIt != rootChildren.end()) { + AuthorNode *authorNode = (AuthorNode*)*nodeIt; + if (authorNode->author() == *it) { + if (!isSubtreeUpToDate(authorNode)) { + updateAuthorSubtree(authorNode); + if (authorNode == topAuthorNode) { + topAuthorNodeIsUpdated = true; + } + } + ++nodeIt; + ++nodeCount; + processed = true; + break; + } else if (comparator(authorNode->author(), *it)) { + nodesToDelete.insert(*nodeIt); + ++nodeIt; + ++nodeCount; + } else { + break; + } + } + if (!processed) { + addAuthorSubtree(*it, nodeCount); + ++nodeCount; + } + } + + nodesToDelete.insert(nodeIt, rootChildren.end()); + + if (topAuthorNodeIsUpdated) { + setFirstVisibleNode(topAuthorNode); + } else if (nodesToDelete.find(topAuthorNode) != nodesToDelete.end()) { + ZLBlockTreeNode *visible = topAuthorNode->previous(); + while (nodesToDelete.find(visible) != nodesToDelete.end()) { + visible = visible->previous(); + } + setFirstVisibleNode(visible); + } + + for (std::set<ZLBlockTreeNode*>::iterator it = nodesToDelete.begin(); it != nodesToDelete.end(); ++it) { + delete *it; + } +} diff --git a/fbreader/src/libraryTree/LibraryByTagView.cpp b/fbreader/src/libraryTree/LibraryByTagView.cpp new file mode 100644 index 0000000..76913f1 --- /dev/null +++ b/fbreader/src/libraryTree/LibraryByTagView.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include "LibraryView.h" +#include "LibraryNodes.h" + +#include "../library/Library.h" +#include "../library/Book.h" +#include "../library/Tag.h" +#include "../libraryActions/BooksUtil.h" + +LibraryByTagView::LibraryByTagView(ZLPaintContext &context) : LibraryView(context) { +} + +void LibraryByTagView::collectTagNodes(const ZLBlockTreeNode &root, std::map<shared_ptr<Tag>,TagNode*,TagComparator> &nodeMap) { + const ZLBlockTreeNode::List &children = root.children(); + for (ZLBlockTreeNode::List::const_iterator it = children.begin(); it != children.end(); ++it) { + if ((*it)->isInstanceOf(TagNode::TYPE_ID)) { + TagNode *tagNode = (TagNode*)*it; + nodeMap[tagNode->tag()] = tagNode; + collectTagNodes(*tagNode, nodeMap); + } + } +} + +void LibraryByTagView::updateBookList(TagNode *tagNode) { + const BookList &books = Library::Instance().books(tagNode->tag()); + const ZLBlockTreeNode::List &subNodes = tagNode->children(); + BookList::const_iterator jt = books.begin(); + ZLBlockTreeNode::List::const_iterator kt = subNodes.begin(); + for (; jt != books.end() && kt != subNodes.end(); ++jt, ++kt) { + if (!(*kt)->isInstanceOf(BookNode::TYPE_ID)) { + break; + } + if (((BookNode*)(*kt))->book()->file() != (*jt)->file()) { + break; + } + } + + std::size_t index = jt - books.begin(); + while (tagNode->children().size() > index) { + ZLBlockTreeNode *bookNode = tagNode->children()[index]; + if (!bookNode->isInstanceOf(BookNode::TYPE_ID)) { + break; + } + delete bookNode; + } + + for (; jt != books.end(); ++jt) { + new BookNode(tagNode, index++, *jt); + } +} + +void LibraryByTagView::makeUpToDate() { + TagList tags; + BooksUtil::collectTagsFromLibrary(tags); + + std::map<shared_ptr<Tag>,TagNode*,TagComparator> nodeMap; + collectTagNodes(rootNode(), nodeMap); + + for (TagList::const_iterator it = tags.begin(); it != tags.end(); ++it) { + shared_ptr<Tag> tag = *it; + TagNode *tagNode = nodeMap[tag]; + if (tagNode == 0) { + tagNode = + (tag.isNull() || tag->parent().isNull()) ? + new TagNode(&rootNode(), tag) : + new TagNode(nodeMap[tag->parent()], tag); + nodeMap[tag] = tagNode; + } + updateBookList(tagNode); + } + + for (TagList::const_iterator it = tags.begin(); it != tags.end(); ++it) { + nodeMap.erase(nodeMap.find(*it)); + } + + for (std::map<shared_ptr<Tag>,TagNode*,TagComparator>::reverse_iterator it = nodeMap.rbegin(); it != nodeMap.rend(); ++it) { + delete it->second; + } +} diff --git a/fbreader/src/libraryTree/LibraryNodes.h b/fbreader/src/libraryTree/LibraryNodes.h new file mode 100644 index 0000000..5f1eab9 --- /dev/null +++ b/fbreader/src/libraryTree/LibraryNodes.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __LIBRARYNODES_H__ +#define __LIBRARYNODES_H__ + +#include "../blockTree/FBReaderNode.h" + +class ZLImage; + +class Author; +class Book; +class Tag; + +class AuthorNode : public FBReaderNode { + +public: + static const ZLTypeId TYPE_ID; + +public: + AuthorNode(ZLBlockTreeView::RootNode *parent, std::size_t atPosition, shared_ptr<Author> author); + void init(); + + shared_ptr<Author> author() const; + +private: + const ZLResource &resource() const; + const ZLTypeId &typeId() const; + shared_ptr<const ZLImage> extractCoverImage() const; + std::string title() const; + +private: + shared_ptr<Author> myAuthor; +}; + +class SeriesNode : public FBReaderNode { + +public: + static const ZLTypeId TYPE_ID; + +public: + SeriesNode(AuthorNode *parent); + void init(); + + shared_ptr<Book> book() const; + +private: + const ZLResource &resource() const; + const ZLTypeId &typeId() const; + shared_ptr<const ZLImage> extractCoverImage() const; + std::string title() const; +}; + +class TagNode : public FBReaderNode { + +public: + static const ZLTypeId TYPE_ID; + +private: + static std::size_t positionToInsert(ZLBlockTreeNode *parent, shared_ptr<Tag> tag); + +public: + TagNode(ZLBlockTreeView::RootNode *parent, shared_ptr<Tag> tag); + TagNode(TagNode *parent, shared_ptr<Tag> tag); + void init(); + + shared_ptr<Tag> tag() const; + +private: + const ZLResource &resource() const; + const ZLTypeId &typeId() const; + shared_ptr<const ZLImage> extractCoverImage() const; + std::string title() const; + +private: + const shared_ptr<Tag> myTag; +}; + +class BookNode : public FBReaderNode { + +public: + static const ZLTypeId TYPE_ID; + +public: + BookNode(AuthorNode *parent, shared_ptr<Book> book); + BookNode(SeriesNode *parent, shared_ptr<Book> book); + BookNode(TagNode *parent, std::size_t atPosition, shared_ptr<Book> book); + + shared_ptr<Book> book() const; + +private: + void init(); + bool highlighted() const; + const ZLResource &resource() const; + const ZLTypeId &typeId() const; + shared_ptr<const ZLImage> extractCoverImage() const; + std::string title() const; + std::string summary() const; + +private: + const shared_ptr<Book> myBook; +}; + +#endif /* __LIBRARYNODES_H__ */ diff --git a/fbreader/src/libraryTree/LibraryView.cpp b/fbreader/src/libraryTree/LibraryView.cpp new file mode 100644 index 0000000..067c865 --- /dev/null +++ b/fbreader/src/libraryTree/LibraryView.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <queue> + +#include <ZLResource.h> + +#include "LibraryView.h" +#include "LibraryNodes.h" + +#include "../library/Library.h" +#include "../library/Book.h" +#include "../options/FBOptions.h" + +LibraryView::LibraryView(ZLPaintContext &context) : ZLBlockTreeView(context), myCollectionRevision(0) { +} + +void LibraryView::paint() { + const std::size_t revision = Library::Instance().revision(); + if (myCollectionRevision < revision) { + myCollectionRevision = revision; + makeUpToDate(); + } + + ZLBlockTreeView::paint(); +} + +const std::string &LibraryView::caption() const { + return ZLResource::resource("library")["caption"].value(); +} + +ZLColor LibraryView::backgroundColor() const { + return FBOptions::Instance().BackgroundColorOption.value(); +} + +void LibraryView::showBook(shared_ptr<Book> book) { + makeUpToDate(); + ZLBlockTreeNode::List bookNodes; + std::queue<ZLBlockTreeNode*> nodesQueue; + nodesQueue.push(&rootNode()); + while (!nodesQueue.empty()) { + const ZLBlockTreeNode::List &children = nodesQueue.front()->children(); + nodesQueue.pop(); + for (ZLBlockTreeNode::List::const_iterator it = children.begin(); it != children.end(); ++it) { + if ((*it)->isInstanceOf(BookNode::TYPE_ID)) { + // TODO: replace with == for shared_ptr<Book> + //if (((BookNode*)*it)->book() == book) { + if (((BookNode*)*it)->book()->file() == book->file()) { + bookNodes.push_back(*it); + } + } else { + nodesQueue.push(*it); + } + } + } + if (bookNodes.empty()) { + return; + } + ZLBlockTreeNode *nodeToShow = bookNodes[0]; + VisibilityMode mode = INVISIBLE; + for (ZLBlockTreeNode::List::iterator it = bookNodes.begin(); it != bookNodes.end(); ++it) { + VisibilityMode nodeMode = visibilityMode(*it); + if ((nodeMode == VISIBLE && mode != VISIBLE) || + (nodeMode != INVISIBLE && mode == INVISIBLE)) { + nodeToShow = *it; + mode = nodeMode; + } + } + ensureVisible(nodeToShow); +} diff --git a/fbreader/src/libraryTree/LibraryView.h b/fbreader/src/libraryTree/LibraryView.h new file mode 100644 index 0000000..40715f6 --- /dev/null +++ b/fbreader/src/libraryTree/LibraryView.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#ifndef __LIBRARYVIEW_H__ +#define __LIBRARYVIEW_H__ + +#include <map> +#include <set> + +#include <ZLBlockTreeView.h> + +#include "../library/Lists.h" + +class Book; +class Author; +class Tag; +class TagComparator; + +class AuthorNode; +class TagNode; + +class LibraryView : public ZLBlockTreeView { + +protected: + LibraryView(ZLPaintContext &context); + +public: + void showBook(shared_ptr<Book>); + +private: + ZLColor backgroundColor() const; + const std::string &caption() const; + +private: + void paint(); + +protected: + virtual void makeUpToDate() = 0; + +private: + std::size_t myCollectionRevision; +}; + +class LibraryByAuthorView : public LibraryView { + +public: + LibraryByAuthorView(ZLPaintContext &context); + +private: + void makeUpToDate(); + + void addAuthorSubtree(shared_ptr<Author> author, std::size_t atPosition); + void fillAuthorSubtree(AuthorNode *node, const std::set<shared_ptr<Book> > &visibleBooks); + bool isSubtreeUpToDate(AuthorNode *node); + void updateAuthorSubtree(AuthorNode *node); +}; + +class LibraryByTagView : public LibraryView { + +public: + LibraryByTagView(ZLPaintContext &context); + +private: + void makeUpToDate(); + + void collectTagNodes(const ZLBlockTreeNode &root, std::map<shared_ptr<Tag>,TagNode*,TagComparator> &nodeMap); + void updateBookList(TagNode *tagNode); +}; + +#endif /* __LIBRARYVIEW_H__ */ diff --git a/fbreader/src/libraryTree/SeriesNode.cpp b/fbreader/src/libraryTree/SeriesNode.cpp new file mode 100644 index 0000000..6d4aafa --- /dev/null +++ b/fbreader/src/libraryTree/SeriesNode.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLImage.h> +#include <ZLResource.h> + +#include "LibraryNodes.h" + +#include "../library/Book.h" + +const ZLTypeId SeriesNode::TYPE_ID(FBReaderNode::TYPE_ID); + +const ZLResource &SeriesNode::resource() const { + return ZLResource::resource("libraryView")["seriesNode"]; +} + +const ZLTypeId &SeriesNode::typeId() const { + return TYPE_ID; +} + +SeriesNode::SeriesNode(AuthorNode *parent) : FBReaderNode(parent) { +} + +void SeriesNode::init() { + registerExpandTreeAction(); +} + +shared_ptr<Book> SeriesNode::book() const { + return ((BookNode&)*children().front()).book(); +} + +std::string SeriesNode::title() const { + return book()->seriesTitle(); +} + +shared_ptr<const ZLImage> SeriesNode::extractCoverImage() const { + const std::vector<ZLBlockTreeNode*> &books = children(); + for (std::vector<ZLBlockTreeNode*>::const_iterator it = books.begin(); it != books.end(); ++it) { + shared_ptr<const ZLImage> bookCover = ((FBReaderNode*)*it)->coverImage(); + if (!bookCover.isNull()) { + return bookCover; + } + } + return 0; +} diff --git a/fbreader/src/libraryTree/TagNode.cpp b/fbreader/src/libraryTree/TagNode.cpp new file mode 100644 index 0000000..7ccd3ac --- /dev/null +++ b/fbreader/src/libraryTree/TagNode.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009-2012 Geometer Plus <[email protected]> + * + * 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. + */ + +#include <ZLResource.h> +#include <ZLImage.h> + +#include "LibraryNodes.h" + +#include "../library/Tag.h" +#include "../libraryActions/LibraryTagActions.h" + +const ZLTypeId TagNode::TYPE_ID(FBReaderNode::TYPE_ID); + +const ZLTypeId &TagNode::typeId() const { + return TYPE_ID; +} + +const ZLResource &TagNode::resource() const { + return ZLResource::resource("libraryView")["tagNode"]; +} + +std::size_t TagNode::positionToInsert(ZLBlockTreeNode *parent, shared_ptr<Tag> tag) { + const ZLBlockTreeNode::List &children = parent->children(); + ZLBlockTreeNode::List::const_reverse_iterator it = children.rbegin(); + for (; it != children.rend(); ++it) { + if (!(*it)->isInstanceOf(TagNode::TYPE_ID) || + TagComparator()(((TagNode*)*it)->tag(), tag)) { + break; + } + } + return children.rend() - it; +} + +TagNode::TagNode(ZLBlockTreeView::RootNode *parent, shared_ptr<Tag> tag) : FBReaderNode(parent, positionToInsert(parent, tag)), myTag(tag) { +} + +TagNode::TagNode(TagNode *parent, shared_ptr<Tag> tag) : FBReaderNode(parent, positionToInsert(parent, tag)), myTag(tag) { +} + +void TagNode::init() { + registerExpandTreeAction(); + if (!myTag.isNull()) { + registerAction(new TagEditAction(myTag)); + registerAction(new TagCloneAction(myTag)); + registerAction(new TagRemoveAction(myTag)); + } +} + +shared_ptr<Tag> TagNode::tag() const { + return myTag; +} + +std::string TagNode::title() const { + if (myTag.isNull()) { + return resource()["noTags"].value(); + } + return myTag->name(); +} + +shared_ptr<const ZLImage> TagNode::extractCoverImage() const { + return defaultCoverImage("booktree-tag.png"); +} |