diff --git a/.gitmodules b/.gitmodules index 4254dc4..7186484 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "redkitty"] path = redkitty url = git@gitea.redkit-lab.work:redkit-lab/redkitty.git +[submodule "external_libs/quazip"] + path = external_libs/quazip + url = https://github.com/stachenov/quazip.git diff --git a/external_libs/quazip.qbs b/external_libs/quazip.qbs new file mode 100644 index 0000000..bf7ce29 --- /dev/null +++ b/external_libs/quazip.qbs @@ -0,0 +1,34 @@ +import qbs + +PSLibrary { + name: "quazip" + + property string quazipPath: path + "/quazip" // Путь к исходникам QuaZip + property string noname: { + console.error("noname" + exportedIncludePaths) + return "noname" + } + + Depends { name: "zlib" } + + Group { + name: "h" + id: qh + files: [ + quazipPath + "/quazip/*.h", + ] + } + + Group { + name: "cpp" + files: [ + quazipPath + "/quazip/*.cpp", + quazipPath + "/quazip/*.c" + ] + } + + // Export { + // Depends { name:"cpp" } + // cpp.includePaths: qh + // } +} diff --git a/project.qbs b/project.qbs index fee6594..c36f82f 100644 --- a/project.qbs +++ b/project.qbs @@ -17,5 +17,9 @@ Project { "src/database/database.qbs", "src/model/model.qbs", "src/restapi/restapi.qbs", + "src/utils/utils.qbs", + "src/repository/repository.qbs", + + "external_libs/quazip.qbs", ] } diff --git a/redkitty b/redkitty index 2316dde..47579f9 160000 --- a/redkitty +++ b/redkitty @@ -1 +1 @@ -Subproject commit 2316ddea7250c3d828a7c4a45f49ea8bc100448b +Subproject commit 47579f9e2e5e2973e1bbf260565563380b53e849 diff --git a/src/cpp-opds.qbs b/src/cpp-opds.qbs index f1b969f..ecf85a1 100644 --- a/src/cpp-opds.qbs +++ b/src/cpp-opds.qbs @@ -22,6 +22,8 @@ PSApplication { Depends { name: "redkit_gen" } Depends { name: "rdbase" } Depends { name: "model" } + Depends { name: "quazip" } + Depends { name: "utils" } cpp.cxxLanguageVersion: "c++20" diff --git a/src/database/database.qbs b/src/database/database.qbs index c1e4a3e..3cdc49d 100644 --- a/src/database/database.qbs +++ b/src/database/database.qbs @@ -11,13 +11,15 @@ PSLibrary { "DATABASE_SQLITE", "DATABASE_LIBRARY" ] - consoleApplication: true Depends { name: "Qt"; submodules: [ "core", "network" ] } Depends { name: "cpp" } Depends { name: "odb.gen" } Depends { name: "rdbase" } + Depends { name: "model" } + + Depends { name: "redkit_gen" } odb.gen.databases: "sqlite" cpp.cxxLanguageVersion: "c++17" diff --git a/src/database/database_utils.cpp b/src/database/database_utils.cpp index 0081295..305a107 100644 --- a/src/database/database_utils.cpp +++ b/src/database/database_utils.cpp @@ -1,57 +1,55 @@ #include "database_utils.h" -#include - -namespace +void addBook(oDBase& db, const QString title, const QVector& authors) { - -// Функция для генерации случайной строки (имени или фамилии) -QString generate_random_string(const QVector& pool) -{ - static std::random_device rd; - static std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, pool.size() - 1); - return pool[dis(gen)]; -} - -// Функция для генерации случайного года -int generate_random_year(int min_year = 1900, int max_year = 2020) -{ - static std::random_device rd; - static std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(min_year, max_year); - return dis(gen); -} - -} // namespace - -QVector fillAuthorDB() -{ - QVector first_names = { - "John", "Jane", "Alex", "Chris", "Robert", "Emily", "James", "Linda", "David", "Sarah", - "Michael", "Elizabeth", "Daniel", "Samantha", "William", "Olivia", "Ethan", "Sophia", "Joshua", "Charlotte", - "Daniel", "Grace", "Benjamin", "Isabella", "Matthew", "Victoria", "Henry", "Abigail", "Samuel", "Megan", - "Lucas", "Lily", "Andrew", "Madison", "Jackson", "Chloe", "Aiden", "Amelia", "Thomas", "Natalie", - "Ryan", "Zoe", "Jack", "Harper", "Elijah", "Ava", "Isaac", "Mia", "Caleb", "Ella" - }; - QVector last_names = { - "Doe", "Smith", "Johnson", "Williams", "Jones", "Brown", "Davis", "Miller", "Wilson", "Moore", - "Taylor", "Anderson", "Thomas", "Jackson", "White", "Harris", "Martin", "Thompson", "Garcia", "Martinez", - "Roberts", "Clark", "Lewis", "Walker", "Young", "Allen", "King", "Wright", "Scott", "Adams", - "Baker", "Gonzalez", "Nelson", "Carter", "Mitchell", "Perez", "Robinson", "Hughes", "Flores", "Cook", - "Rogers", "Gutierrez", "Ramirez", "Diaz", "Perez", "Ross", "Sanders", "Price", "Howard", "Cooper" - }; - - QVector vecTest; - - for (int i = 0; i < 50; ++i) + odb::transaction t(db.begin()); + try { - QString first_name = generate_random_string(first_names); - QString last_name = generate_random_string(last_names); - int birth_year = generate_random_year(1900, 2000); + // 1. Создаем/получаем книгу + auto books = db.query(odb::query::title == title); + SH book; - vecTest.push_back({ first_name, last_name, birth_year }); + if (books.empty()) + { + book = SH::create(); + book->setTitle(title); + + db.persist(book); + } + else + { + book = books.begin().load(); // Берем первую найденную книгу + } + + // 2. Обрабатываем авторов + for (const auto& name : authors) + { + auto authors = db.query(odb::query::fullName == name); + SH author = authors.empty() ? SH::create() : authors.begin().load(); + + if (authors.empty()) + { + author->setFullName(name); + db.persist(author); + } + + // Проверяем и создаем связь + + auto links = db.query( + odb::query::author->id == author->id() + && odb::query::book->id == book->id()); + + if (links.empty()) + { + db.persist(SH::create(author, book)); + } + } + + t.commit(); + } + catch (...) + { + t.rollback(); + throw; } - - return vecTest; } diff --git a/src/database/database_utils.h b/src/database/database_utils.h index a4f227a..5dccabe 100644 --- a/src/database/database_utils.h +++ b/src/database/database_utils.h @@ -1,3 +1,4 @@ +#include #include #include @@ -27,11 +28,11 @@ using oDBase = odb::sqlite::database; using uDBase = U; -struct testData -{ - QString first; - QString last; - int age; -}; +#include +#include +#include +#include +#include +#include -QVector DATABASE_EXPORT fillAuthorDB(); +void DATABASE_EXPORT addBook(oDBase& db, const QString title, const QVector& authors); diff --git a/src/main.cpp b/src/main.cpp index 247ddbd..6c61dee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -8,110 +9,98 @@ #include /* Опыты с odb */ -#include // Должен быть здесь -#include -#include // Должен быть здесь -#include #include // create_database +#include #include #include +#include +#include + void fillBooksBD(uDBase& db) { try { - QVector> authors = { - SH::create("George", "Orwell", 142), - SH::create("J.K.", "Rowling", 56), - SH::create("J.R.R.", "Tolkien", 81), - SH::create("Leo", "Tolstoy", 189), - SH::create("Fyodor", "Dostoevsky", 174), - SH::create("Mark", "Twain", 183), - SH::create("Charles", "Dickens", 208), - SH::create("Virginia", "Woolf", 134), - SH::create("Ernest", "Hemingway", 122), - SH::create("Gabriel", "García Márquez", 98), - SH::create("Franz", "Kafka", 100), - SH::create("Harper", "Lee", 64), - SH::create("William", "Shakespeare", 459), - SH::create("Oscar", "Wilde", 155), - SH::create("Aldous", "Huxley", 123), - SH::create("Jane", "Austen", 210), - SH::create("John", "Steinbeck", 116), - SH::create("Agatha", "Christie", 124), - SH::create("Isaac", "Asimov", 105) + QVector authors = { + Author_S("George Orwell"), + Author_S("J.K. Rowling"), + Author_S("J.R.R. Tolkien"), + Author_S("Leo Tolstoy"), + Author_S("Fyodor Dostoevsky"), + Author_S("Mark Twain"), + Author_S("Charles Dickens"), + Author_S("Virginia Woolf"), + Author_S("Ernest Hemingway"), + Author_S("Gabriel García Márquez"), + Author_S("Franz Kafka"), + Author_S("Harper Lee"), + Author_S("William Shakespeare"), + Author_S("Oscar Wilde"), + Author_S("Aldous Huxley"), + Author_S("Jane Austen"), + Author_S("John Steinbeck"), + Author_S("Agatha Christie"), + Author_S("Isaac Asimov"), }; - // Список книг - QVector books = { - Book_S("1984", authors[0], 1949), - Book_S("Harry Potter and the Philosopher's Stone", authors[1], 1997), - Book_S("The Hobbit", authors[2], 1937), - Book_S("War and Peace", authors[3], 1869), - Book_S("Crime and Punishment", authors[4], 1866), - Book_S("Adventures of Huckleberry Finn", authors[5], 1884), - Book_S("A Tale of Two Cities", authors[6], 1859), - Book_S("Mrs. Dalloway", authors[7], 1925), - Book_S("The Old Man and the Sea", authors[8], 1952), - Book_S("One Hundred Years of Solitude", authors[9], 1967), - Book_S("The Trial", authors[10], 1925), - Book_S("To Kill a Mockingbird", authors[11], 1960), - Book_S("Macbeth", authors[12], 1606), - Book_S("The Picture of Dorian Gray", authors[13], 1890), - Book_S("Brave New World", authors[14], 1932), - Book_S("Pride and Prejudice", authors[15], 1813), - Book_S("The Brothers Karamazov", authors[4], 1880), - Book_S("The Grapes of Wrath", authors[16], 1939), - Book_S("Murder on the Orient Express", authors[17], 1934), - Book_S("I, Robot", authors[18], 1950), - Book_S("Animal Farm", authors[0], 1945), - Book_S("Harry Potter and the Chamber of Secrets", authors[1], 1998), - Book_S("The Lord of the Rings: The Fellowship of the Ring", authors[2], 1954), - Book_S("Anna Karenina", authors[3], 1878), - Book_S("The Idiot", authors[4], 1869), - Book_S("The Adventures of Tom Sawyer", authors[5], 1876), - Book_S("Oliver Twist", authors[6], 1837), - Book_S("To the Lighthouse", authors[7], 1927), - Book_S("For Whom the Bell Tolls", authors[8], 1940), - Book_S("Love in the Time of Cholera", authors[9], 1985), - Book_S("The Metamorphosis", authors[10], 1915), - Book_S("Go Set a Watchman", authors[11], 2015), - Book_S("King Lear", authors[12], 1605), - Book_S("The Importance of Being Earnest", authors[13], 1895), - Book_S("Brave New World Revisited", authors[14], 1958), - Book_S("Emma", authors[15], 1815), - Book_S("The Double", authors[4], 1846), - Book_S("Of Mice and Men", authors[16], 1937), - Book_S("And Then There Were None", authors[17], 1939), - Book_S("The Foundation Trilogy", authors[18], 1951), - Book_S("Down and Out in Paris and London", authors[0], 1933), - Book_S("Harry Potter and the Prisoner of Azkaban", authors[1], 1999), - Book_S("The Lord of the Rings: The Two Towers", authors[2], 1954), - Book_S("War and Peace", authors[3], 1869), - Book_S("The Brothers Karamazov", authors[4], 1880), - Book_S("The Prince and the Pauper", authors[5], 1881), - Book_S("David Copperfield", authors[6], 1850), - Book_S("The Waves", authors[7], 1931), - Book_S("A Farewell to Arms", authors[8], 1929), - Book_S("Chronicle of a Death Foretold", authors[9], 1981) - }; + addBook(*db, "Очень странная книжка", { "Автор 1", "Автор 2", "Авторк 3" }); - // Сохранение авторов в базу данных - { - odb::core::transaction t(db->begin()); - for (auto& author : authors) - db->persist(author); - t.commit(); - } + addBook(*db, "1984", { authors[0].fullName() }); + addBook(*db, "Harry Potter and the Philosopher's Stone", { authors[1].fullName() }); + addBook(*db, "The Hobbit", { authors[2].fullName() }); + addBook(*db, "War and Peace", { authors[3].fullName() }); + addBook(*db, "Crime and Punishment", { authors[4].fullName() }); + addBook(*db, "Adventures of Huckleberry Finn", { authors[5].fullName() }); + addBook(*db, "A Tale of Two Cities", { authors[6].fullName() }); + addBook(*db, "Mrs. Dalloway", { authors[7].fullName() }); + addBook(*db, "The Old Man and the Sea", { authors[8].fullName() }); + addBook(*db, "One Hundred Years of Solitude", { authors[9].fullName() }); + addBook(*db, "The Trial", { authors[10].fullName() }); + addBook(*db, "To Kill a Mockingbird", { authors[11].fullName() }); + addBook(*db, "Macbeth", { authors[12].fullName() }); + addBook(*db, "The Picture of Dorian Gray", { authors[13].fullName() }); + addBook(*db, "Brave New World", { authors[14].fullName() }); + addBook(*db, "Pride and Prejudice", { authors[15].fullName() }); + addBook(*db, "The Brothers Karamazov", { authors[4].fullName() }); + addBook(*db, "The Grapes of Wrath", { authors[16].fullName() }); + addBook(*db, "Murder on the Orient Express", { authors[17].fullName() }); + addBook(*db, "I, Robot", { authors[18].fullName() }); + addBook(*db, "Animal Farm", { authors[0].fullName() }); + addBook(*db, "Harry Potter and the Chamber of Secrets", { authors[1].fullName() }); + addBook(*db, "The Lord of the Rings: The Fellowship of the Ring", { authors[2].fullName() }); + addBook(*db, "Anna Karenina", { authors[3].fullName() }); + addBook(*db, "The Idiot", { authors[4].fullName() }); + addBook(*db, "The Adventures of Tom Sawyer", { authors[5].fullName() }); + addBook(*db, "Oliver Twist", { authors[6].fullName() }); + addBook(*db, "To the Lighthouse", { authors[7].fullName() }); + addBook(*db, "For Whom the Bell Tolls", { authors[8].fullName() }); + addBook(*db, "Love in the Time of Cholera", { authors[9].fullName() }); + addBook(*db, "The Metamorphosis", { authors[10].fullName() }); + addBook(*db, "Go Set a Watchman", { authors[11].fullName() }); + addBook(*db, "King Lear", { authors[12].fullName() }); + addBook(*db, "The Importance of Being Earnest", { authors[13].fullName() }); + addBook(*db, "Brave New World Revisited", { authors[14].fullName() }); + addBook(*db, "Emma", { authors[15].fullName() }); + addBook(*db, "The Double", { authors[4].fullName() }); + addBook(*db, "Of Mice and Men", { authors[16].fullName() }); + addBook(*db, "And Then There Were None", { authors[17].fullName() }); + addBook(*db, "The Foundation Trilogy", { authors[18].fullName() }); + addBook(*db, "Down and Out in Paris and London", { authors[0].fullName() }); + addBook(*db, "Harry Potter and the Prisoner of Azkaban", { authors[1].fullName() }); + addBook(*db, "The Lord of the Rings: The Two Towers", { authors[2].fullName() }); + addBook(*db, "War and Peace", { authors[3].fullName() }); + addBook(*db, "The Brothers Karamazov", { authors[4].fullName() }); + addBook(*db, "The Prince and the Pauper", { authors[5].fullName() }); + addBook(*db, "David Copperfield", { authors[6].fullName() }); + addBook(*db, "The Waves", { authors[7].fullName() }); + addBook(*db, "A Farewell to Arms", { authors[8].fullName() }); + addBook(*db, "Chronicle of a Death Foretold", { authors[9].fullName() }); - // Сохранение книг в базу данных - { - odb::core::transaction t(db->begin()); - for (auto& book : books) - db->persist(book); - t.commit(); - } + addBook(*db, "1984", { "George Orwell" }); + addBook(*db, "Harry Potter and the Philosopher's Stone", { "J.K. Rowling" }); + + addBook(*db, "Очень странная книжка 2", { "Автор 4", "Авторк 3" }); std::cout << "Test data added successfully." << std::endl; } @@ -129,23 +118,28 @@ int main(int argc, char* argv[]) uDBase db(openDB(dbPath)); // TODO Как-то нужно выполнять лишь раз - fillBooksBD(db); - - // Сохранение дополнителньых авторов в базу данных - { - auto authors = fillAuthorDB(); - odb::core::transaction t(db->begin()); - for (auto& author : authors) - { - SH tempAuthor = SH::create(author.first, author.last, author.age); - db->persist(tempAuthor); - } - t.commit(); - } + // fillBooksBD(db); RestApiServer server(*db); server.start(8080); + QString zipArzh = "/home/alex/repos/exp/cpp-opds/f.fb2-631519-634744.zip"; + + auto z = ZipWrapper(zipArzh); + const auto books = z.work(); + + for (const auto& book : books) + { + try + { + addBook(*db, book.title, book.authors); + } + catch (const odb::exception& e) + { + std::cerr << "Error adding test data: " << e.what() << std::endl; + } + } + // Set up code that uses the Qt event loop here. // Call a.quit() or a.exit() to quit the application. // A not very useful example would be including @@ -157,5 +151,6 @@ int main(int argc, char* argv[]) // If you do not need a running Qt event loop, remove the call // to a.exec() or use the Non-Qt Plain C++ Application template. + // qWarning() << "S EXIT"; return a.exec(); } diff --git a/src/model/author_s.h b/src/model/author_s.h deleted file mode 100644 index bb9ea34..0000000 --- a/src/model/author_s.h +++ /dev/null @@ -1,64 +0,0 @@ -// file : hello/person.hxx -// copyright : not copyrighted - public domain - -#ifndef AUTHOR_S_H -#define AUTHOR_S_H - -#include "model_global.h" - -#include - -#include -#include -#include - -#pragma db object -class MODEL_EXPORT Author_S -{ -public: - Author_S() = default; - - Author_S(const QString& firstN, - const QString& lastN, - const unsigned short age) : - m_firstName(firstN), - m_lastName(lastN), - m_age(age) - { - } - - unsigned long long id() const { return m_id; } - QString firstName() const { return m_firstName; } - QString lastName() const { return m_lastName; } - unsigned short age() const { return m_age; } - - QString full_name() const { return m_firstName + " " + m_lastName; } - - void age(unsigned short age) { m_age = age; } - -private: - friend class odb::access; - -private: -#pragma db id auto - quint64 m_id; - - QString m_firstName; - QString m_lastName; - quint64 m_age; -}; - -#pragma db view object(Author_S) -struct person_stat -{ -#pragma db column("count(" + Author_S::m_id + ")") - std::size_t count; - -#pragma db column("min(" + Author_S::m_age + ")") - unsigned short min_age; - -#pragma db column("max(" + Author_S::m_age + ")") - unsigned short max_age; -}; - -#endif // AUTHOR_S_H diff --git a/src/model/book_s.h b/src/model/book_s.h deleted file mode 100644 index 8a82ded..0000000 --- a/src/model/book_s.h +++ /dev/null @@ -1,64 +0,0 @@ -// file : hello/person.hxx -// copyright : not copyrighted - public domain - -#ifndef BOOK_S_H -#define BOOK_S_H - -#include "model_global.h" - -#include -#include -#include -#include - -#include "author_s.h" - -#pragma db object -class MODEL_EXPORT Book_S -{ -public: - Book_S() = default; - - Book_S(const QString& name, - const SH& author, - const int year) - { - m_author = author; - m_name = name; - m_year = year; - }; - - unsigned long long id() const { return m_id; } - SH author() const { return m_author; } - QString name() const { return m_name; } - int year() const { return m_year; } - -private: - friend class odb::access; - -private: -#pragma db id auto - quint64 m_id; - - SH m_author; - QString m_name; - quint8 m_year; -}; - -// #pragma db view object(Book_S) object(Author_S = author:Book_S::m_author) -// struct BookByAuthorView -// { -// #pragma db column(Book_S::m_id) -// quint64 book_id; - -// #pragma db column(Book_S::m_name) -// QString book_name; - -// #pragma db column(Book_S::m_year) -// qint8 year; - -// #pragma db column(Author_S::m_first + " " + Author_S::m_last) -// QString author_full_name; -// }; - -#endif // BOOK_S_H diff --git a/src/model/books/author_book_s.h b/src/model/books/author_book_s.h new file mode 100644 index 0000000..ea131d3 --- /dev/null +++ b/src/model/books/author_book_s.h @@ -0,0 +1,47 @@ +#ifndef AUTHOR_BOOK_H +#define AUTHOR_BOOK_H + +#include + +#include "author_s.h" +#include "book_s.h" + +#pragma db object +class MODEL_EXPORT AuthorBook_S +{ +private: + AuthorBook_S() = default; + +public: + AuthorBook_S(SH author, + SH book) : + m_author(author), + m_book(book) {} + + quint64 id() const { return m_id; } + void setId(quint64 newId) { m_id = newId; } + + SH author() const { return m_author; } + void setAuthor(const SH& newAuthor) { m_author = newAuthor; } + + SH book() const { return m_book; } + void setBook(const SH& newBook) { m_book = newBook; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + +#pragma db not_null + SH m_author; + +#pragma db not_null + SH m_book; + +#pragma db index("author_book_unique") member(m_author) member(m_book) unique +}; + +#endif // AUTHOR_BOOK_H diff --git a/src/model/books/author_s.h b/src/model/books/author_s.h new file mode 100644 index 0000000..5912262 --- /dev/null +++ b/src/model/books/author_s.h @@ -0,0 +1,42 @@ +#ifndef AUTHOR_S_H +#define AUTHOR_S_H + +#include + +#pragma db object +class MODEL_EXPORT Author_S +{ +public: + Author_S() = default; + Author_S(const QString& fullName) : + m_fullName(fullName) {} + + quint64 id() const { return m_id; } + void setId(quint64 newId) { m_id = newId; } + + QString fullName() const { return m_fullName; } + void setFullName(const QString& newFullName) { m_fullName = newFullName; } + + QString langCode() const { return m_langCode; } + void setLangCode(const QString& newLangCode) { m_langCode = newLangCode; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + + QString m_fullName; + QString m_langCode; +}; + +#pragma db view object(Author_S) +struct person_stat +{ +#pragma db column("count(" + Author_S::m_id + ")") + std::size_t count; +}; + +#endif // AUTHOR_S_H diff --git a/src/model/books/book_s.h b/src/model/books/book_s.h new file mode 100644 index 0000000..194c5a1 --- /dev/null +++ b/src/model/books/book_s.h @@ -0,0 +1,43 @@ +#ifndef BOOK_S_H +#define BOOK_S_H + +#include + +#include + +#pragma db object +class MODEL_EXPORT Book_S +{ +public: + Book_S() = default; + + quint64 id() const { return m_id; } + void setId(const quint64& newId) { m_id = newId; } + + QString title() const { return m_title; } + void setTitle(const QString& newTitle) { m_title = newTitle; } + + quint8 year() const { return m_year; } + void setYear(const quint8& newYear) { m_year = newYear; } + + QDateTime lastModified() const { return m_lastModified; } + void setLastModified(const QDateTime& newLastModified) { m_lastModified = newLastModified; } + + QString lang() const { return m_lang; } + void setLang(const QString& newLang) { m_lang = newLang; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + + QString m_title; + quint8 m_year; + QDateTime m_lastModified; + QString m_lang; +}; + +#endif // BOOK_S_H diff --git a/src/model/books/genre_book_s.h b/src/model/books/genre_book_s.h new file mode 100644 index 0000000..9607e3d --- /dev/null +++ b/src/model/books/genre_book_s.h @@ -0,0 +1,46 @@ +#ifndef GENRE_BOOK_S_H +#define GENRE_BOOK_S_H + +#include + +#include "book_s.h" +#include "genre_s.h" + +#pragma db object +class GenreBook_S +{ +private: + GenreBook_S() = default; + +public: + GenreBook_S(const SH& genreId, const SH& bookId) : + m_genreId(genreId), + m_bookId(bookId) {} + + quint64 id() const { return m_id; } + void setId(quint64 newId) { m_id = newId; } + + SH genreId() const { return m_genreId; } + void setGenreId(const SH& newGenreId) { m_genreId = newGenreId; } + + SH bookId() const { return m_bookId; } + void setBookId(const SH& newBookId) { m_bookId = newBookId; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + +#pragma db not_null + SH m_genreId; + +#pragma db not_null + SH m_bookId; + +#pragma db index("genre_book_unique") member(m_genreId) member(m_bookId) unique +}; + +#endif // GENRE_BOOK_S_H diff --git a/src/model/books/genre_s.h b/src/model/books/genre_s.h new file mode 100644 index 0000000..0e4d95c --- /dev/null +++ b/src/model/books/genre_s.h @@ -0,0 +1,29 @@ +#ifndef GENRE_H +#define GENRE_H + +#include + +#pragma db object +class MODEL_EXPORT Genre_S +{ +public: + Genre_S() = default; + + quint64 id() const { return m_id; } + void setId(const quint64& newId) { m_id = newId; } + + QString name() const { return m_name; } + void setName(const QString& newName) { m_name = newName; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + + QString m_name; +}; + +#endif // GENRE_H diff --git a/src/model/books/manutomanybase.h b/src/model/books/manutomanybase.h new file mode 100644 index 0000000..c894e70 --- /dev/null +++ b/src/model/books/manutomanybase.h @@ -0,0 +1,10 @@ +#ifndef MANUTOMANYBASE_H +#define MANUTOMANYBASE_H + +class ManuToManyBase +{ +public: + ManuToManyBase(); +}; + +#endif // MANUTOMANYBASE_H diff --git a/src/model/books/series_book_s.h b/src/model/books/series_book_s.h new file mode 100644 index 0000000..9ef4c0f --- /dev/null +++ b/src/model/books/series_book_s.h @@ -0,0 +1,46 @@ +#ifndef SERIES_BOOK_S_H +#define SERIES_BOOK_S_H + +#include + +#include "book_s.h" +#include "series_s.h" + +#pragma db object +class MODEL_EXPORT SeriesBook_S +{ +private: + SeriesBook_S() = default; + +public: + SeriesBook_S(const SH& serieId, const SH& bookId) : + m_serieId(serieId), + m_bookId(bookId) {} + + quint64 id() const { return m_id; } + void setId(quint64 newId) { m_id = newId; } + + SH serieId() const { return m_serieId; } + void setSerieId(const SH& newSerieId) { m_serieId = newSerieId; } + + SH bookId() const { return m_bookId; } + void setBookId(const SH& newBookId) { m_bookId = newBookId; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + +#pragma db not_null + SH m_serieId; + +#pragma db not_null + SH m_bookId; + +#pragma db index("series_book_unique") member(m_serieId) member(m_bookId) unique +}; + +#endif // SERIES_BOOK_S_H diff --git a/src/model/books/series_s.h b/src/model/books/series_s.h new file mode 100644 index 0000000..0df4634 --- /dev/null +++ b/src/model/books/series_s.h @@ -0,0 +1,29 @@ +#ifndef SERIES_H +#define SERIES_H + +#include + +#pragma db object +class MODEL_EXPORT Series_S +{ +public: + Series_S() = default; + + quint64 id() const { return m_id; } + void setId(const quint64& newId) { m_id = newId; } + + QString name() const { return m_serName; } + void setName(const QString& newSerName) { m_serName = newSerName; } + +private: + friend class odb::access; + +private: +public: +#pragma db id auto + quint64 m_id; + + QString m_serName; +}; + +#endif // SERIES_H diff --git a/src/model/model.qbs b/src/model/model.qbs index fbd8c8d..40e34f2 100644 --- a/src/model/model.qbs +++ b/src/model/model.qbs @@ -20,17 +20,27 @@ PSLibrary { Depends { name: "rdbase" } Depends { name: "redkit_gen" } - redkit_gen.includeModules: ["JsonSerializer"] + redkit_gen.includeModules: [redkit_gen.module.JsonSerializer, + redkit_gen.module.SettingsSerializer,] odb.gen.databases: "sqlite" cpp.cxxLanguageVersion: "c++17" + Group { + id: headers + name: "headers" + files: [ + "model_global.h", + ] + } + Group { id: odbs name: "odb" files: [ "**/*.h", ] + excludeFiles: headers.files fileTags: ["hpp", "odbxx", "rgen"] } diff --git a/src/model/model_global.h b/src/model/model_global.h index c01f3b5..ee08f08 100644 --- a/src/model/model_global.h +++ b/src/model/model_global.h @@ -9,4 +9,7 @@ #define MODEL_EXPORT Q_DECL_IMPORT #endif +#include +#include + #endif // MODEL_GLOBAL_H diff --git a/src/model/settings/settings.h b/src/model/settings/settings.h new file mode 100644 index 0000000..3ab49e5 --- /dev/null +++ b/src/model/settings/settings.h @@ -0,0 +1,23 @@ +#ifndef SETTINGS_S_H +#define SETTINGS_S_H + +#include + +#pragma db object +class MODEL_EXPORT Settings_S +{ +public: + Settings_S() = default; + + quint64 id() const { return m_id; } + void setId(const quint64& newId) { m_id = newId; } + +private: + friend class odb::access; + +private: +#pragma db id auto + quint64 m_id; +}; + +#endif // SETTINGS_S_H diff --git a/src/repository/authorrepository.cpp b/src/repository/authorrepository.cpp new file mode 100644 index 0000000..f28bc09 --- /dev/null +++ b/src/repository/authorrepository.cpp @@ -0,0 +1,81 @@ +#include "authorrepository.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace repository +{ + +AuthorRepository::AuthorRepository(odb::core::database& db) : + m_db(db) +{} + +QVector AuthorRepository::findAll() +{ + odb::transaction t(m_db.begin()); + odb::result res(m_db.query()); + + QVector authors; + + for (auto it = res.begin(); it != res.end(); ++it) + { + const auto& author = *it; + authors.push_back(author); + } + + t.commit(); + + return authors; +} + +Author_S AuthorRepository::findById(int id) +{ + odb::transaction t(m_db.begin()); + odb::result res(m_db.query(odb::query::id == id)); + + Author_S author; + res.value(author); + + t.commit(); + + return author; +} + +QVector AuthorRepository::findByBook(const int& bookId) +{ + odb::transaction t(m_db.begin()); + + QVector authors; + + using ABQuery = odb::query; + using ABResult = odb::result; + ABResult abResult(m_db.query(ABQuery::book == bookId)); + + for (const AuthorBook_S& ab : abResult) + { + // Загружаем каждую книгу по ID + SH author(m_db.load(ab.author()->id())); + authors.push_back(*author.data()); + } + t.commit(); + + return authors; +} + +QVector AuthorRepository::findByBook(const QString& book_name) +{ + odb::transaction t(m_db.begin()); + auto book_s = m_db.query(odb::query::title == book_name).one(); + + return findByBook(book_s->id()); +} + +} // namespace repository diff --git a/src/repository/authorrepository.h b/src/repository/authorrepository.h new file mode 100644 index 0000000..76c8454 --- /dev/null +++ b/src/repository/authorrepository.h @@ -0,0 +1,41 @@ +#ifndef AUTHORREPOSITORY_H +#define AUTHORREPOSITORY_H + +#include "repository_global.h" + +#include + +#include +#include + +namespace repository +{ + +class REPOSITORY_EXPORT AuthorRepository +{ +public: + AuthorRepository(odb::core::database& db); + + // Получить всех авторов + QVector findAll(); + + // Найти автора по id + Author_S findById(int id); + + // Сохранить книгу (создать или обновить) + // void save(const Book_S& book); + + // Удалить автора + // void remove(int id); + + // Найти авторов по книге + QVector findByBook(const int& book_id); + QVector findByBook(const QString& bookName); + +private: + odb::core::database& m_db; +}; + +} // namespace repository + +#endif // AUTHORREPOSITORY_H diff --git a/src/repository/bookrepository.cpp b/src/repository/bookrepository.cpp new file mode 100644 index 0000000..af7ddee --- /dev/null +++ b/src/repository/bookrepository.cpp @@ -0,0 +1,96 @@ +#include "bookrepository.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace repository +{ + +BookRepository::BookRepository(odb::core::database& db) : + m_db(db) +{} + +QVector BookRepository::findAll() +{ + odb::transaction t(m_db.begin()); + odb::result res(m_db.query()); + + QVector books; + + for (auto it = res.begin(); it != res.end(); ++it) + { + const auto& book = *it; + books.push_back(book); + } + + t.commit(); + + return books; +} + +Book_S BookRepository::findById(int id) +{ + odb::transaction t(m_db.begin()); + odb::result res(m_db.query(odb::query::id == id)); + + Book_S book; + res.value(book); + + t.commit(); + + return book; +} + +// void BookRepository::save(const Book_S& book) +// { +// } + +void BookRepository::remove(int id) +{ + odb::transaction t(m_db.begin()); + odb::result res(m_db.query(odb::query::id == id)); + res.one().reset(); + t.commit(); +} + +QVector BookRepository::findByAuthor(const int& authorId) +{ + odb::transaction t(m_db.begin()); + + QVector books; + + using ABQuery = odb::query; + using ABResult = odb::result; + ABResult abResult(m_db.query(ABQuery::author == authorId)); + + for (const AuthorBook_S& ab : abResult) + { + // Загружаем каждую книгу по ID + SH book(m_db.load(ab.book()->id())); + books.push_back(*book.data()); + } + + t.commit(); + + return books; +} + +QVector BookRepository::findByAuthor(const QString& author) +{ + odb::transaction t(m_db.begin()); + auto author_s = m_db.query(odb::query::fullName == author).one(); + + return findByAuthor(author_s->id()); +} + +} // namespace repository diff --git a/src/repository/bookrepository.h b/src/repository/bookrepository.h new file mode 100644 index 0000000..f1918b8 --- /dev/null +++ b/src/repository/bookrepository.h @@ -0,0 +1,41 @@ +#ifndef BOOKREPOSITORY_H +#define BOOKREPOSITORY_H + +#include "repository_global.h" + +#include + +#include +#include + +namespace repository +{ + +class REPOSITORY_EXPORT BookRepository +{ +public: + BookRepository(odb::core::database& db); + + // Получить все книги + QVector findAll(); + + // Найти книгу по ID + Book_S findById(int id); + + // Сохранить книгу (создать или обновить) + // void save(const Book_S& book); + + // Удалить книгу + void remove(int id); + + // Найти книги по автору + QVector findByAuthor(const QString& authorName); + QVector findByAuthor(const int& authorId); + +private: + odb::core::database& m_db; +}; + +} // namespace repository + +#endif // BOOKREPOSITORY_H diff --git a/src/repository/repository.qbs b/src/repository/repository.qbs new file mode 100644 index 0000000..f7649c8 --- /dev/null +++ b/src/repository/repository.qbs @@ -0,0 +1,33 @@ +/*! + \qmltype cpp-opds + \inherits Project + \brief Описание +*/ +PSLibrary { + name: "repository" + cpp.defines: [ + "REPOSITORY_LIBRARY" + ] + + Depends { name: "Qt"; submodules: [ "core" ] } + Depends { name: "model" } + + Depends { name: "rdbase" } + Depends { name: "odb.gen" } + Depends { name: "database" } + + Group { + name: "cpp" + files: [ + "**/*.h", + "**/*.cpp", + ] + } + + cpp.dynamicLibraries: [ + "odb-sqlite", + "odb-qt", + "odb", + "sqlite3" + ] +} diff --git a/src/repository/repository_global.h b/src/repository/repository_global.h new file mode 100644 index 0000000..b2eeb4b --- /dev/null +++ b/src/repository/repository_global.h @@ -0,0 +1,12 @@ +#ifndef REPOSITORY_GLOBAL_H +#define REPOSITORY_GLOBAL_H + +#include + +#if defined(REPOSITORY_LIBRARY) +#define REPOSITORY_EXPORT Q_DECL_EXPORT +#else +#define REPOSITORY_EXPORT Q_DECL_IMPORT +#endif + +#endif // REPOSITORY_GLOBAL_H diff --git a/src/restapi/restapi.qbs b/src/restapi/restapi.qbs index 046ae13..8bb41ac 100644 --- a/src/restapi/restapi.qbs +++ b/src/restapi/restapi.qbs @@ -19,6 +19,7 @@ WPSLibrary { Depends { name: "redkit_gen" } Depends { name: "rdbase" } Depends { name: "model" } + Depends { name: "repository" } cpp.cxxLanguageVersion: "c++20" diff --git a/src/restapi/restapiserver.cpp b/src/restapi/restapiserver.cpp index b9820e2..b84c4a2 100644 --- a/src/restapi/restapiserver.cpp +++ b/src/restapi/restapiserver.cpp @@ -5,10 +5,13 @@ #include #include -#include // Должен быть здесь -#include -#include // Должен быть здесь -#include +#include // Должен быть здесь +#include +#include // Должен быть здесь +#include + +#include +#include #include #include @@ -63,61 +66,90 @@ QByteArray RestApiServer::processRequest(const QString& request) if (request.startsWith("GET /books/author/")) { + repository::BookRepository b(m_db); + QString author = request.section(' ', 1, 1).section('/', 3, 3).replace("%20", " "); - quint64 ageReq = author.toInt(); - - QStringList nameParts = author.split(' '); - QString firstName = nameParts.size() > 0 ? nameParts[0] : ""; - QString lastName = nameParts.size() > 1 ? nameParts[1] : ""; - - odb::transaction t(m_db.begin()); - - auto books = m_db.query(odb::query::author->id == ageReq); + qWarning() << author; + auto books = b.findByAuthor(author); QJsonArray jArray; for (const auto& book : books) { QJsonObject j; j["id"] = QString::number(book.id()); - j["name"] = book.name(); - j["author"] = book.author()->full_name(); - j["year"] = book.year(); + j["title"] = book.title(); + jArray.push_back(j); } auto jDoc = QJsonDocument(jArray); - t.commit(); + return "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + jDoc.toJson(QJsonDocument::Indented); + } + + if (request.startsWith("GET /books/id")) + { + repository::BookRepository b(m_db); + + QString book_id = request.section(' ', 1, 1).section('/', 3, 3).replace("%20", " "); + qWarning() << book_id; + + auto book = b.findById(book_id.toInt()); + + QJsonObject j; + j["id"] = QString::number(book.id()); + QJsonArray authors; + + repository::AuthorRepository a(m_db); + + for (const auto& author : a.findByBook(book.id())) + { + QJsonObject jj; + jj["id"] = QString::number(author.id()); + jj["fullName"] = author.fullName(); + authors.push_back(jj); + } + + j["authors"] = authors; + j["title"] = book.title(); + + auto jDoc = QJsonDocument(j); return "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + jDoc.toJson(QJsonDocument::Indented); } if (request.startsWith("GET /books")) { - odb::transaction t(m_db.begin()); - odb::result res(m_db.query()); + repository::BookRepository b(m_db); QJsonArray jArray; - for (auto it = res.begin(); it != res.end(); ++it) + for (const auto& book : b.findAll()) { - const auto& book = *it; - QJsonObject j; j["id"] = QString::number(book.id()); - j["title"] = book.name(); - j["author"] = book.author()->full_name(); - j["year"] = book.year(); + j["title"] = book.title(); + + QJsonArray authors; + repository::AuthorRepository a(m_db); + for (const auto& author : a.findByBook(book.id())) + { + QJsonObject jj; + jj["id"] = QString::number(author.id()); + jj["fullName"] = author.fullName(); + authors.push_back(jj); + } + j["authors"] = authors; + jArray.push_back(j); } auto jDoc = QJsonDocument(jArray); - t.commit(); return "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + jDoc.toJson(QJsonDocument::Indented); } - if (request.startsWith("GET /author")) + if (request.startsWith("GET /authors")) { - odb::transaction t(m_db.begin()); - odb::result res(m_db.query()); + repository::AuthorRepository a(m_db); + auto res = a.findAll(); QJsonArray jArray; for (auto it = res.begin(); it != res.end(); ++it) @@ -126,13 +158,22 @@ QByteArray RestApiServer::processRequest(const QString& request) QJsonObject j; j["id"] = QString::number(author.id()); - j["first"] = author.firstName(); - j["last"] = author.lastName(); - j["age"] = author.age(); + j["fullName"] = author.fullName(); + + QJsonArray books; + repository::BookRepository b(m_db); + for (const auto& book : b.findByAuthor(author.id())) + { + QJsonObject jj; + jj["id"] = QString::number(book.id()); + jj["title"] = book.title(); + books.push_back(jj); + } + j["books"] = books; + jArray.push_back(j); } auto jDoc = QJsonDocument(jArray); - t.commit(); return "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n" + jDoc.toJson(QJsonDocument::Indented); } diff --git a/src/utils/fb2extractor.cpp b/src/utils/fb2extractor.cpp new file mode 100644 index 0000000..72ddb61 --- /dev/null +++ b/src/utils/fb2extractor.cpp @@ -0,0 +1,101 @@ +#include "fb2extractor.h" + +// FB2Extractor::FB2Extractor() +// { +// } + +FB2Extractor::FB2Extractor(QuaZipFile& file) : + m_file(&file) +{ +} + +FB2Extractor::~FB2Extractor() +{ + m_file.close(); +} + +Fb2Metadata FB2Extractor::parse() +{ + bool isOpen = m_file.open(QIODevice::ReadOnly); + // int zipError = fb2File.getZipError(); + if (!isOpen) + { + qWarning() << "file in extractor is not open"; + return {}; + } + + QXmlStreamReader xmlData(&m_file); + + Fb2Metadata meta; + QString currentElement; + bool inTitleInfo = false; + bool inAuthor = false; + QString currentAuthor; + + while (!xmlData.atEnd()) + { + switch (xmlData.readNext()) + { + case QXmlStreamReader::StartElement: + currentElement = xmlData.name().toString(); + + if (currentElement == "title-info") + { + inTitleInfo = true; + } + else if (inTitleInfo) + { + if (currentElement == "book-title") + { + meta.title = xmlData.readElementText(); + } + else if (currentElement == "genre") + { + meta.genres << xmlData.readElementText(); + } + else if (currentElement == "author") + { + inAuthor = true; + currentAuthor.clear(); + } + else if (inAuthor && (currentElement == "first-name" || currentElement == "last-name" || currentElement == "middle-name")) + { + currentAuthor += xmlData.readElementText() + " "; + } + } + break; + + case QXmlStreamReader::EndElement: + if (xmlData.name().toString() == "title-info") + { + inTitleInfo = false; + } + else if (xmlData.name().toString() == "author" && inAuthor) + { + meta.authors << currentAuthor.trimmed(); + inAuthor = false; + } + break; + + case QXmlStreamReader::Characters: + // Обработка текста уже делается в readElementText() + break; + + default: + break; + } + + // Прерываем парсинг, если нашли все метаданные + if (!meta.title.isEmpty() && !meta.authors.isEmpty() && !meta.genres.isEmpty()) + { + break; + } + } + + if (xmlData.hasError()) + { + qWarning() << "XML parsing error:" << xmlData.errorString(); + } + + return meta; +} diff --git a/src/utils/fb2extractor.h b/src/utils/fb2extractor.h new file mode 100644 index 0000000..8966acb --- /dev/null +++ b/src/utils/fb2extractor.h @@ -0,0 +1,36 @@ +#ifndef FB2EXTRACTOR_H +#define FB2EXTRACTOR_H + +#include "utils_global.h" + +#include +#include +#include + +#include + +struct Fb2Metadata +{ + QString title; // Название книги + QVector authors; // Авторы + QStringList genres; // Жанры +}; + +Fb2Metadata UTILS_EXPORT parseFb2Metadata(QXmlStreamReader& sr); + +class UTILS_EXPORT FB2Extractor +{ +public: + FB2Extractor(QuaZipFile& file); + ~FB2Extractor(); + + /*! + * \brief Распарсить инфу из содержимого + */ + Fb2Metadata parse(); + +private: + QuaZipFile m_file; +}; + +#endif // FB2EXTRACTOR_H diff --git a/src/utils/utils.qbs b/src/utils/utils.qbs new file mode 100644 index 0000000..fced4a7 --- /dev/null +++ b/src/utils/utils.qbs @@ -0,0 +1,22 @@ +/*! + \qmltype cpp-opds + \inherits Project + \brief Описание +*/ +PSLibrary { + name: "utils" + cpp.defines: [ + "UTILS_LIBRARY" + ] + + Depends { name: "Qt"; submodules: [ "core" ] } + Depends { name: "quazip" } + + Group { + name: "cpp" + files: [ + "**/*.h", + "**/*.cpp", + ] + } +} diff --git a/src/utils/utils_global.h b/src/utils/utils_global.h new file mode 100644 index 0000000..7daa3fb --- /dev/null +++ b/src/utils/utils_global.h @@ -0,0 +1,12 @@ +#ifndef UTILS_GLOBAL_H +#define UTILS_GLOBAL_H + +#include + +#if defined(UTILS_LIBRARY) +#define UTILS_EXPORT Q_DECL_EXPORT +#else +#define UTILS_EXPORT Q_DECL_IMPORT +#endif + +#endif // UTILS_GLOBAL_H diff --git a/src/utils/zipwrapper.cpp b/src/utils/zipwrapper.cpp new file mode 100644 index 0000000..c8460c4 --- /dev/null +++ b/src/utils/zipwrapper.cpp @@ -0,0 +1,142 @@ +#include "zipwrapper.h" + +#include "fb2extractor.h" + +#include + +namespace +{ +Fb2Metadata parse(QuaZipFile& m_file) +{ + bool isOpen = m_file.open(QIODevice::ReadOnly); + // int zipError = fb2File.getZipError(); + if (!isOpen) + { + qWarning() << "file in extractor is not open"; + return {}; + } + + QXmlStreamReader xmlData(&m_file); + + Fb2Metadata meta; + QString currentElement; + bool inTitleInfo = false; + bool inAuthor = false; + QString currentAuthor; + + while (!xmlData.atEnd()) + { + switch (xmlData.readNext()) + { + case QXmlStreamReader::StartElement: + currentElement = xmlData.name().toString(); + + if (currentElement == "title-info") + { + inTitleInfo = true; + } + else if (inTitleInfo) + { + if (currentElement == "book-title") + { + meta.title = xmlData.readElementText(); + } + else if (currentElement == "genre") + { + meta.genres << xmlData.readElementText(); + } + else if (currentElement == "author") + { + inAuthor = true; + currentAuthor.clear(); + } + else if (inAuthor && (currentElement == "first-name" || currentElement == "last-name" || currentElement == "middle-name")) + { + currentAuthor += xmlData.readElementText() + " "; + } + } + break; + + case QXmlStreamReader::EndElement: + if (xmlData.name().toString() == "title-info") + { + inTitleInfo = false; + } + else if (xmlData.name().toString() == "author" && inAuthor) + { + meta.authors << currentAuthor.trimmed(); + inAuthor = false; + } + break; + + case QXmlStreamReader::Characters: + // Обработка текста уже делается в readElementText() + break; + + default: + break; + } + + // Прерываем парсинг, если нашли все метаданные + if (!meta.title.isEmpty() && !meta.authors.isEmpty() && !meta.genres.isEmpty()) + { + break; + } + } + + if (xmlData.hasError()) + { + qWarning() << "XML parsing error:" << xmlData.errorString(); + } + + return meta; +} + +} // namespace + +ZipWrapper::ZipWrapper(const QString& zipFilePath) : + m_zip(zipFilePath) +{ + m_zip.open(QuaZip::mdUnzip); + isOpen(); +} + +ZipWrapper::~ZipWrapper() +{ + // В любом случае закрываем архив + m_zip.close(); +} + +QVector ZipWrapper::work() +{ + if (!isOpen()) + return {}; + + // int i = 0; + QVector parsedBooks; + for (bool more = m_zip.goToFirstFile(); more; more = m_zip.goToNextFile()) + { + // ++i; + if (m_zip.getCurrentFileName().endsWith(".fb2")) + { + QuaZipFile fb2File(&m_zip); + + auto fb2Extr = parse(fb2File); + // qWarning() << i << ":" << fb2Extr.title << fb2Extr.authors << fb2Extr.genres; + parsedBooks.push_back(fb2Extr); + } + else + qWarning() << "Неизвестный файл" << &m_zip; + } + + return parsedBooks; +} + +bool ZipWrapper::isOpen() +{ + if (m_zip.isOpen()) + return true; + + qWarning() << "Не удалось открыть архив:" << m_zip.getZipName(); + return false; +} diff --git a/src/utils/zipwrapper.h b/src/utils/zipwrapper.h new file mode 100644 index 0000000..fdfcf09 --- /dev/null +++ b/src/utils/zipwrapper.h @@ -0,0 +1,29 @@ +#ifndef ZIPWRAPPER_H +#define ZIPWRAPPER_H + +#include "utils_global.h" + +#include +#include +#include + +#include +#include // TODO для совместимости. Временно + +#include "fb2extractor.h" + +class UTILS_EXPORT ZipWrapper +{ +public: + ZipWrapper(const QString& zipFilePath); + ~ZipWrapper(); + + QVector work(); + +private: + bool isOpen(); + + QuaZip m_zip; +}; + +#endif // ZIPWRAPPER_H