diff options
Diffstat (limited to 'fbreader/src/library/Library.cpp')
| -rw-r--r-- | fbreader/src/library/Library.cpp | 439 |
1 files changed, 0 insertions, 439 deletions
diff --git a/fbreader/src/library/Library.cpp b/fbreader/src/library/Library.cpp deleted file mode 100644 index 8ee1f36..0000000 --- a/fbreader/src/library/Library.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2004-2012 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. - */ - -#include <queue> -#include <algorithm> - -#include <ZLibrary.h> -#include <ZLStringUtil.h> -#include <ZLFile.h> -#include <ZLDir.h> -#include <ZLDialogManager.h> - -#include "Library.h" -#include "Book.h" -#include "Author.h" -#include "Tag.h" - -#include "../formats/FormatPlugin.h" - -#include "../database/booksdb/BooksDBUtil.h" -#include "../database/booksdb/BooksDB.h" - -shared_ptr<Library> Library::ourInstance; -const std::size_t Library::MaxRecentListSize = 10; - -Library &Library::Instance() { - if (ourInstance.isNull()) { - ourInstance = new Library(); - } - return *ourInstance; -} - -static const std::string OPTIONS = "Options"; - -Library::Library() : - PathOption(ZLCategoryKey::CONFIG, OPTIONS, "BookPath", ""), - ScanSubdirsOption(ZLCategoryKey::CONFIG, OPTIONS, "ScanSubdirs", true), - CollectAllBooksOption(ZLCategoryKey::CONFIG, OPTIONS, "CollectAllBooks", false), - myBuildMode(BUILD_ALL), - myRevision(0) { - BooksDBUtil::getRecentBooks(myRecentBooks); -} - -void Library::collectBookFileNames(std::set<std::string> &bookFileNames) const { - std::set<std::string> dirs; - collectDirNames(dirs); - - while (!dirs.empty()) { - std::string dirname = *dirs.begin(); - dirs.erase(dirs.begin()); - - ZLFile dirfile(dirname); - std::vector<std::string> files; - bool inZip = false; - - shared_ptr<ZLDir> dir = dirfile.directory(); - if (dir.isNull()) { - continue; - } - - if (dirfile.isArchive()) { - ZLFile phys(dirfile.physicalFilePath()); - if (!BooksDBUtil::checkInfo(phys)) { - BooksDBUtil::resetZipInfo(phys); - BooksDBUtil::saveInfo(phys); - } - BooksDBUtil::listZipEntries(dirfile, files); - inZip = true; - } else { - dir->collectFiles(files, true); - } - if (!files.empty()) { - const bool collectBookWithoutMetaInfo = CollectAllBooksOption.value(); - for (std::vector<std::string>::const_iterator jt = files.begin(); jt != files.end(); ++jt) { - const std::string fileName = (inZip) ? (*jt) : (dir->itemPath(*jt)); - ZLFile file(fileName); - if (PluginCollection::Instance().plugin(file, !collectBookWithoutMetaInfo) != 0) { - bookFileNames.insert(fileName); - } else if (file.isArchive()) { - if (myScanSubdirs || !inZip) { - dirs.insert(fileName); - } - } - } - } - } -} - -void Library::rebuildBookSet() const { - myBooks.clear(); - myExternalBooks.clear(); - - std::map<std::string, shared_ptr<Book> > booksMap; - BooksDBUtil::getBooks(booksMap); - - std::set<std::string> fileNamesSet; - collectBookFileNames(fileNamesSet); - - // collect books from book path - for (std::set<std::string>::iterator it = fileNamesSet.begin(); it != fileNamesSet.end(); ++it) { - std::map<std::string, shared_ptr<Book> >::iterator jt = booksMap.find(*it); - if (jt == booksMap.end()) { - insertIntoBookSet(BooksDBUtil::getBook(*it)); - } else { - insertIntoBookSet(jt->second); - booksMap.erase(jt); - } - } - - // other books from our database - for (std::map<std::string, shared_ptr<Book> >::iterator jt = booksMap.begin(); jt != booksMap.end(); ++jt) { - shared_ptr<Book> book = jt->second; - if (!book.isNull()) { - if (BooksDB::Instance().checkBookList(*book)) { - insertIntoBookSet(book); - myExternalBooks.insert(book); - } - } - } -} - -std::size_t Library::revision() const { - if (myBuildMode == BUILD_NOTHING && - (myScanSubdirs != ScanSubdirsOption.value() || - myPath != PathOption.value())) { - myPath = PathOption.value(); - myScanSubdirs = ScanSubdirsOption.value(); - myBuildMode = BUILD_ALL; - } - - return (myBuildMode == BUILD_NOTHING) ? myRevision : myRevision + 1; -} - -class LibrarySynchronizer : public DBRunnable { - -public: - LibrarySynchronizer(Library::BuildMode mode) : myBuildMode(mode) { } - -private: - bool run() { - Library &library = Library::Instance(); - - if (myBuildMode & Library::BUILD_COLLECT_FILES_INFO) { - library.rebuildBookSet(); - } - - if (myBuildMode & Library::BUILD_UPDATE_BOOKS_INFO) { - library.rebuildMaps(); - } - return true; - } - -private: - const Library::BuildMode myBuildMode; -}; - -class LibrarySynchronizerWrapper : public ZLRunnable { - -public: - LibrarySynchronizerWrapper(Library::BuildMode mode) : myRunnable(mode) { } - -private: - void run() { - BooksDB::Instance().executeAsTransaction(myRunnable); - } - -private: - LibrarySynchronizer myRunnable; -}; - -void Library::synchronize() const { - if (myScanSubdirs != ScanSubdirsOption.value() || - myPath != PathOption.value()) { - myPath = PathOption.value(); - myScanSubdirs = ScanSubdirsOption.value(); - myBuildMode = BUILD_ALL; - } - - if (myBuildMode == BUILD_NOTHING) { - return; - } - - LibrarySynchronizerWrapper synchronizer(myBuildMode); - myBuildMode = BUILD_NOTHING; - ZLDialogManager::Instance().wait(ZLResourceKey("loadingBookList"), synchronizer); - - ++myRevision; -} - -void Library::rebuildMaps() const { - myAuthors.clear(); - myBooksByAuthor.clear(); - myTags.clear(); - myBooksByTag.clear(); - - for (BookSet::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { - if ((*it).isNull()) { - continue; - } - - const AuthorList &bookAuthors = (*it)->authors(); - if (bookAuthors.empty()) { - myBooksByAuthor[0].push_back(*it); - } else { - for(AuthorList::const_iterator jt = bookAuthors.begin(); jt != bookAuthors.end(); ++jt) { - myBooksByAuthor[*jt].push_back(*it); - } - } - - const TagList &bookTags = (*it)->tags(); - if (bookTags.empty()) { - myBooksByTag[0].push_back(*it); - } else { - for(TagList::const_iterator kt = bookTags.begin(); kt != bookTags.end(); ++kt) { - myBooksByTag[*kt].push_back(*it); - } - } - } - for (BooksByAuthor::iterator mit = myBooksByAuthor.begin(); mit != myBooksByAuthor.end(); ++mit) { - myAuthors.push_back(mit->first); - std::sort(mit->second.begin(), mit->second.end(), BookComparator()); - } - for (BooksByTag::iterator mjt = myBooksByTag.begin(); mjt != myBooksByTag.end(); ++mjt) { - myTags.push_back(mjt->first); - std::sort(mjt->second.begin(), mjt->second.end(), BookComparator()); - } -} - -void Library::collectDirNames(std::set<std::string> &nameSet) const { - std::queue<std::string> nameQueue; - - std::string path = myPath; - int pos = path.find(ZLibrary::PathDelimiter); - while (pos != -1) { - nameQueue.push(path.substr(0, pos)); - path.erase(0, pos + 1); - pos = path.find(ZLibrary::PathDelimiter); - } - if (!path.empty()) { - nameQueue.push(path); - } - - std::set<std::string> resolvedNameSet; - while (!nameQueue.empty()) { - std::string name = nameQueue.front(); - nameQueue.pop(); - ZLFile f(name); - const std::string resolvedName = f.resolvedPath(); - if (resolvedNameSet.find(resolvedName) == resolvedNameSet.end()) { - if (myScanSubdirs) { - shared_ptr<ZLDir> dir = f.directory(); - if (!dir.isNull()) { - std::vector<std::string> subdirs; - dir->collectSubDirs(subdirs, true); - for (std::vector<std::string>::const_iterator it = subdirs.begin(); it != subdirs.end(); ++it) { - nameQueue.push(dir->itemPath(*it)); - } - } - } - resolvedNameSet.insert(resolvedName); - nameSet.insert(name); - } - } -} - -void Library::updateBook(shared_ptr<Book> book) { - BooksDB::Instance().saveBook(book); - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); -} - -void Library::addBook(shared_ptr<Book> book) { - if (!book.isNull()) { - BooksDB::Instance().saveBook(book); - insertIntoBookSet(book); - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); - } -} - -void Library::removeBook(shared_ptr<Book> book) { - if (!book.isNull()) { - BookSet::iterator it = myBooks.find(book); - if (it != myBooks.end()) { - myBooks.erase(it); - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); - } - BooksDB::Instance().deleteFromBookList(*book); - bool recentListChanged = false; - for (BookList::iterator it = myRecentBooks.begin(); it != myRecentBooks.end();) { - if ((*it)->file() == book->file()) { - it = myRecentBooks.erase(it); - recentListChanged = true; - } else { - ++it; - } - } - if (recentListChanged) { - BooksDB::Instance().saveRecentBooks(myRecentBooks); - } - } -} - -const AuthorList &Library::authors() const { - synchronize(); - return myAuthors; -} - -const TagList &Library::tags() const { - synchronize(); - return myTags; -} - -const BookList &Library::books(shared_ptr<Author> author) const { - synchronize(); - return myBooksByAuthor[author]; -} - -const BookList &Library::books(shared_ptr<Tag> tag) const { - synchronize(); - return myBooksByTag[tag]; -} - -void Library::collectSeriesTitles(shared_ptr<Author> author, std::set<std::string> &titles) const { - const BookList &bookList = books(author); - for (BookList::const_iterator it = bookList.begin(); it != bookList.end(); ++it) { - const std::string ¤t = (*it)->seriesTitle(); - if (!current.empty()) { - titles.insert(current); - } - } -} - -void Library::removeTag(shared_ptr<Tag> tag, bool includeSubTags) { - for (BookSet::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { - if ((*it)->removeTag(tag, includeSubTags)) { - BooksDB::Instance().saveTags(*it); - } - } - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); -} - -void Library::renameTag(shared_ptr<Tag> from, shared_ptr<Tag> to, bool includeSubTags) { - if (to != from) { - synchronize(); - for (BookSet::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { - BooksDBUtil::renameTag(*it, from, to, includeSubTags); - } - } - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); -} - -void Library::cloneTag(shared_ptr<Tag> from, shared_ptr<Tag> to, bool includeSubTags) { - if (to != from) { - synchronize(); - for (BookSet::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { - BooksDBUtil::cloneTag(*it, from, to, includeSubTags); - } - } - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); -} - -bool Library::hasBooks(shared_ptr<Tag> tag) const { - synchronize(); - const BooksByTag::const_iterator it = myBooksByTag.find(tag); - return it != myBooksByTag.end() && !it->second.empty(); -} - -bool Library::hasSubtags(shared_ptr<Tag> tag) const { - const TagList &tagList = tags(); - const TagList::const_iterator it = - std::upper_bound(tagList.begin(), tagList.end(), tag, TagComparator()); - return it != tagList.end() && tag->isAncestorOf(*it); -} - -void Library::replaceAuthor(shared_ptr<Author> from, shared_ptr<Author> to) { - if (to != from) { - for (BookSet::const_iterator it = myBooks.begin(); it != myBooks.end(); ++it) { - if ((*it)->replaceAuthor(from, to)) { - BooksDB::Instance().saveAuthors(*it); - } - } - myBuildMode = (BuildMode)(myBuildMode | BUILD_UPDATE_BOOKS_INFO); - } -} - -Library::RemoveType Library::canRemove(shared_ptr<Book> book) const { - synchronize(); - return (RemoveType)( - (myExternalBooks.find(book) != myExternalBooks.end() ? - REMOVE_FROM_LIBRARY : REMOVE_DONT_REMOVE) | - (BooksDBUtil::canRemoveFile(book->file().path()) ? - REMOVE_FROM_DISK : REMOVE_DONT_REMOVE) - ); -} - -void Library::insertIntoBookSet(shared_ptr<Book> book) const { - if (!book.isNull()) { - myBooks.insert(book); - } -} - -const BookList &Library::recentBooks() const { - return myRecentBooks; -} - -void Library::addBookToRecentList(shared_ptr<Book> book) { - if (book.isNull()) { - return; - } - for (BookList::iterator it = myRecentBooks.begin(); it != myRecentBooks.end(); ++it) { - if ((*it)->file() == book->file()) { - if (it == myRecentBooks.begin()) { - return; - } - myRecentBooks.erase(it); - break; - } - } - myRecentBooks.insert(myRecentBooks.begin(), book); - if (myRecentBooks.size() > MaxRecentListSize) { - myRecentBooks.erase(myRecentBooks.begin() + MaxRecentListSize, myRecentBooks.end()); - } - BooksDB::Instance().saveRecentBooks(myRecentBooks); -} |
