WIP: Новые таблицы и изменение старых структур #6
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -4,3 +4,6 @@
|
|||||||
[submodule "redkitty"]
|
[submodule "redkitty"]
|
||||||
path = redkitty
|
path = redkitty
|
||||||
url = git@gitea.redkit-lab.work:redkit-lab/redkitty.git
|
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
34
external_libs/quazip.qbs
Normal 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
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -17,5 +17,6 @@ Project {
|
|||||||
"src/database/database.qbs",
|
"src/database/database.qbs",
|
||||||
"src/model/model.qbs",
|
"src/model/model.qbs",
|
||||||
"src/restapi/restapi.qbs",
|
"src/restapi/restapi.qbs",
|
||||||
|
"external_libs/quazip.qbs",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
2
redkitty
2
redkitty
Submodule redkitty updated: 2316ddea72...47579f9e2e
@@ -22,12 +22,15 @@ PSApplication {
|
|||||||
Depends { name: "redkit_gen" }
|
Depends { name: "redkit_gen" }
|
||||||
Depends { name: "rdbase" }
|
Depends { name: "rdbase" }
|
||||||
Depends { name: "model" }
|
Depends { name: "model" }
|
||||||
|
Depends { name: "quazip" }
|
||||||
|
|
||||||
cpp.cxxLanguageVersion: "c++20"
|
cpp.cxxLanguageVersion: "c++20"
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
name: "cpp"
|
name: "cpp"
|
||||||
files: [
|
files: [
|
||||||
|
"fb2extractor.cpp",
|
||||||
|
"fb2extractor.h",
|
||||||
"main.cpp",
|
"main.cpp",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/fb2extractor.cpp
Normal file
79
src/fb2extractor.cpp
Normal 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
26
src/fb2extractor.h
Normal 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
|
||||||
95
src/main.cpp
95
src/main.cpp
@@ -1,5 +1,6 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@@ -14,6 +15,69 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#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)
|
void fillBooksBD(uDBase& db)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -119,6 +183,36 @@ 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";
|
||||||
|
|
||||||
|
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.
|
// Set up code that uses the Qt event loop here.
|
||||||
// Call a.quit() or a.exit() to quit the application.
|
// Call a.quit() or a.exit() to quit the application.
|
||||||
// A not very useful example would be including
|
// 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
|
// 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";
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user