WIP: Новые таблицы и изменение старых структур #6

Draft
alex wants to merge 12 commits from Новые-таблицы into master
6 changed files with 155 additions and 126 deletions
Showing only changes of commit 4568ef65db - Show all commits

View File

@@ -18,67 +18,6 @@
#include <utils/fb2extractor.h> #include <utils/fb2extractor.h>
#include <utils/zipwrapper.h> #include <utils/zipwrapper.h>
QMap<QString, QString> readFb2MetadataFromZip(const QString& zipPath)
{
QMap<QString, QString> metadata;
QuaZip zip(zipPath);
if (!zip.open(QuaZip::mdUnzip))
{
qWarning() << "Failed to open ZIP archive";
return metadata;
}
int count = 0;
for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile())
{
++count;
qWarning() << "*********" << count << "*********";
// Получение информации о файле
// QuaZipFileInfo fileInfo;
// if (zip.getCurrentFileInfo(&fileInfo))
// {
// qDebug() << "File:" << fileInfo.name
// << "Size:" << fileInfo.uncompressedSize << "bytes"
// << "Compressed:" << fileInfo.compressedSize << "bytes"
// << "Modified:" << fileInfo.dateTime.toString(Qt::ISODate);
// }
QString fb2FileName = zip.getCurrentFileName();
qWarning() << fb2FileName;
// if (fb2FileName.isEmpty())
// {
// qWarning() << "No FB2 file found in archive";
// zip.close();
// return metadata;
// }
// // Читаем FB2 файл из архива
// // qWarning() << "Читаем FB2 файл из архива" << fb2FileName;
QuaZipFile fb2File(&zip);
// bool isOpen = fb2File.open(QIODevice::ReadOnly);
// int zipError = fb2File.getZipError();
// if (!isOpen || zipError != UNZ_OK)
// {
// qWarning() << "Failed to open FB2 file in archive";
// zip.close();
// return metadata;
// }
// // Парсим XML метаданные
// QXmlStreamReader fXmlBook(&fb2File);
// const auto data = parseFb2Metadata(fXmlBook);
// qWarning() << data.title << data.authors << data.genres;
// qWarning() << "*********" << count << "*********";
}
return metadata;
}
void fillBooksBD(uDBase& db) void fillBooksBD(uDBase& db)
{ {
try try
@@ -184,21 +123,20 @@ int main(int argc, char* argv[])
RestApiServer server(*db); RestApiServer server(*db);
server.start(8080); server.start(8080);
// QString zipArzh = "f.fb2-631519-634744.zip";
QString zipArzh = "/home/alex/repos/exp/cpp-opds/f.fb2-631519-634744.zip"; QString zipArzh = "/home/alex/repos/exp/cpp-opds/f.fb2-631519-634744.zip";
const auto books = readFb2MetadataFromZip(zipArzh);
// qWarning() << " books.count()" << books.count();
auto z = ZipWrapper(zipArzh); auto z = ZipWrapper(zipArzh);
for (const auto& filename : z.getFiles()) const auto books = z.work();
for (const auto& book : books)
{ {
if (filename.endsWith(".fb2")) try
{ {
auto zf = z.getFile(filename).data(); addBook(*db, book.title, book.authors);
auto fb2File = FB2Extractor(*zf); }
const auto book = fb2File.parse(); catch (const odb::exception& e)
// qWarning() << book.title; {
std::cerr << "Error adding test data: " << e.what() << std::endl;
} }
} }
@@ -213,6 +151,6 @@ int main(int argc, char* argv[])
// If you do not need a running Qt event loop, remove the call // 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. // to a.exec() or use the Non-Qt Plain C++ Application template.
qWarning() << "S EXIT"; // qWarning() << "S EXIT";
return a.exec(); return a.exec();
} }

View File

@@ -112,19 +112,18 @@ QByteArray RestApiServer::processRequest(const QString& request)
QJsonObject j; QJsonObject j;
j["id"] = QString::number(book.id()); j["id"] = QString::number(book.id());
// QJsonObject author; // QJsonObject author;
// author["id"] = QString::number(book.author()->id()); // author["id"] = QString::number(book.author()->id());
// author["fullName"] = book.author()->fullName(); // author["fullName"] = book.author()->fullName();
// author["langCode"] = book.author()->langCode(); // author["langCode"] = book.author()->langCode();
// j["author"] = author; // j["author"] = author;
// // j["series"] = book.series()->serName(); // j["series"] = book.series()->serName();
// // j["genre"] = book.genre()->name(); // j["genre"] = book.genre()->name();
// j["title"] = book.title(); j["title"] = book.title();
// j["year"] = book.year(); // j["year"] = book.year();
// j["lastModified"] = book.lastModified().toString(); // j["lastModified"] = book.lastModified().toString();
// j["lang"] = book.lang(); // j["lang"] = book.lang();
// jArray.push_back(j); jArray.push_back(j);
} }
auto jDoc = QJsonDocument(jArray); auto jDoc = QJsonDocument(jArray);
t.commit(); t.commit();

View File

@@ -16,6 +16,14 @@ FB2Extractor::~FB2Extractor()
Fb2Metadata FB2Extractor::parse() 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); QXmlStreamReader xmlData(&m_file);
Fb2Metadata meta; Fb2Metadata meta;

View File

@@ -12,7 +12,7 @@
struct Fb2Metadata struct Fb2Metadata
{ {
QString title; // Название книги QString title; // Название книги
QStringList authors; // Авторы QVector<QString> authors; // Авторы
QStringList genres; // Жанры QStringList genres; // Жанры
}; };

View File

@@ -1,60 +1,142 @@
#include "zipwrapper.h" #include "zipwrapper.h"
#include <external_libs/quazip/quazip/quazip.h> #include "fb2extractor.h"
#include <external_libs/quazip/quazip/quazipfile.h> #include <external_libs/quazip/quazip/quazipfile.h>
// zipwrapper.cpp namespace
#include "zipwrapper.h" {
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 {};
}
#include <QDebug> 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) : ZipWrapper::ZipWrapper(const QString& zipFilePath) :
m_zip(new QuaZip(zipFilePath)) m_zip(zipFilePath)
{ {
if (!m_zip->open(QuaZip::mdUnzip)) m_zip.open(QuaZip::mdUnzip);
{ isOpen();
qWarning() << "Failed to open archive:" << zipFilePath
<< "Error:" << m_zip->getZipError();
}
} }
ZipWrapper::~ZipWrapper() ZipWrapper::~ZipWrapper()
{ {
if (isOpen()) // В любом случае закрываем архив
{ m_zip.close();
m_zip->close();
}
} }
QStringList ZipWrapper::getFiles() QVector<Fb2Metadata> ZipWrapper::work()
{ {
if (!isOpen()) if (!isOpen())
return {}; return {};
return m_zip->getFileNameList();
// int i = 0;
QVector<Fb2Metadata> 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;
} }
QSharedPointer<QuaZipFile> ZipWrapper::getFile(const QString& filename) return parsedBooks;
{
QSharedPointer<QuaZipFile> file(new QuaZipFile(m_zip.data()));
if (!file->open(QIODevice::ReadOnly))
{
qWarning() << "Failed to open file:" << filename
<< "Error:" << file->getZipError();
return nullptr;
} }
for (bool more = m_zip->goToFirstFile(); more; more = m_zip->goToNextFile()) bool ZipWrapper::isOpen()
if (m_zip->getCurrentFileName() == filename)
{ {
auto shqzf = QSharedPointer<QuaZipFile>(new QuaZipFile(m_zip.data())); if (m_zip.isOpen())
return shqzf; return true;
};
return file; qWarning() << "Не удалось открыть архив:" << m_zip.getZipName();
} return false;
bool ZipWrapper::isOpen() const
{
return m_zip && m_zip->isOpen();
} }

View File

@@ -1,29 +1,31 @@
// zipwrapper.h
#ifndef ZIPWRAPPER_H #ifndef ZIPWRAPPER_H
#define ZIPWRAPPER_H #define ZIPWRAPPER_H
#include "utils_global.h" #include "utils_global.h"
#include <QScopedPointer> #include <QDebug>
#include <QString> #include <QString>
#include <QStringList> #include <QXmlStreamReader>
#include <QSharedPointer>
class QuaZip;
class QuaZipFile;
#include <external_libs/quazip/quazip/quazip.h>
#include <external_libs/quazip/quazip/quazipfile.h> // TODO для совместимости. Временно
#include "fb2extractor.h"
class UTILS_EXPORT ZipWrapper class UTILS_EXPORT ZipWrapper
{ {
public: public:
explicit ZipWrapper(const QString& zipFilePath); ZipWrapper(const QString& zipFilePath);
~ZipWrapper(); ~ZipWrapper();
QStringList getFiles(); QVector<Fb2Metadata> work();
QSharedPointer<QuaZipFile> getFile(const QString& filename);
bool isOpen() const;
private: private:
QSharedPointer<QuaZip> m_zip; bool isOpen();
QuaZip m_zip;
}; };
#endif // ZIPWRAPPER_H #endif // ZIPWRAPPER_H