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

Draft
alex wants to merge 12 commits from Новые-таблицы into master
8 changed files with 242 additions and 1 deletions
Showing only changes of commit 34fcabc04e - Show all commits

3
.gitmodules vendored
View File

@@ -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

34
external_libs/quazip.qbs Normal file
View File

@@ -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
// }
}

View File

@@ -17,5 +17,6 @@ Project {
"src/database/database.qbs",
"src/model/model.qbs",
"src/restapi/restapi.qbs",
"external_libs/quazip.qbs",
]
}

View File

@@ -22,12 +22,15 @@ PSApplication {
Depends { name: "redkit_gen" }
Depends { name: "rdbase" }
Depends { name: "model" }
Depends { name: "quazip" }
cpp.cxxLanguageVersion: "c++20"
Group {
name: "cpp"
files: [
"fb2extractor.cpp",
"fb2extractor.h",
"main.cpp",
]
}

79
src/fb2extractor.cpp Normal file
View File

@@ -0,0 +1,79 @@
#include "fb2extractor.h"
// FB2Extractor::FB2Extractor() {}
Fb2Metadata parseFb2Metadata(QXmlStreamReader &sr)
{
Fb2Metadata meta;
QString currentElement;
bool inTitleInfo = false;
bool inAuthor = false;
QString currentAuthor;
while (!sr.atEnd())
{
switch (sr.readNext())
{
case QXmlStreamReader::StartElement:
currentElement = sr.name().toString();
if (currentElement == "title-info")
{
inTitleInfo = true;
}
else if (inTitleInfo)
{
if (currentElement == "book-title")
{
meta.title = sr.readElementText();
}
else if (currentElement == "genre")
{
meta.genres << sr.readElementText();
}
else if (currentElement == "author")
{
inAuthor = true;
currentAuthor.clear();
}
else if (inAuthor && (currentElement == "first-name" || currentElement == "last-name" || currentElement == "middle-name"))
{
currentAuthor += sr.readElementText() + " ";
}
}
break;
case QXmlStreamReader::EndElement:
if (sr.name().toString() == "title-info")
{
inTitleInfo = false;
}
else if (sr.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 (sr.hasError())
{
qWarning() << "XML parsing error:" << sr.errorString();
}
return meta;
}

26
src/fb2extractor.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef FB2EXTRACTOR_H
#define FB2EXTRACTOR_H
#include <QDebug>
#include <QXmlStreamReader>
#include <QString>
#include <external_libs/quazip/quazip/quazip.h>
#include <external_libs/quazip/quazip/quazipfile.h>
// class FB2Extractor
// {
// public:
// FB2Extractor();
// };
struct Fb2Metadata
{
QString title;
QStringList authors;
QStringList genres;
};
Fb2Metadata parseFb2Metadata(QXmlStreamReader& sr);
#endif // FB2EXTRACTOR_H

View File

@@ -1,5 +1,6 @@
#include <QCoreApplication>
#include <QDataStream>
#include <QPointer>
#include <QSharedPointer>
#include <QString>
@@ -14,6 +15,69 @@
#include <iostream>
#include "fb2extractor.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();
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)
{
try
@@ -119,6 +183,36 @@ int main(int argc, char* argv[])
RestApiServer server(*db);
server.start(8080);
// QString zipArzh = "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();
// QuaZip zip(zipArzh);
// if (!zip.open(QuaZip::mdUnzip))
// {
// qWarning() << "Failed to open archive";
// }
// else
// {
// qWarning() << "Total files:" << zip.getEntriesCount();
// for (bool more = zip.goToFirstFile(); more; more = zip.goToNextFile())
// {
// QuaZipFileInfo fileInfo;
// if (zip.getCurrentFileInfo(&fileInfo))
// {
// qDebug() << "File:" << fileInfo.name
// << "Size:" << fileInfo.uncompressedSize << "bytes"
// << "Compressed:" << fileInfo.compressedSize << "bytes"
// << "Modified:" << fileInfo.dateTime.toString(Qt::ISODate);
// }
// }
// }
// zip.close();
// 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
@@ -130,5 +224,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();
}