Merge pull request #378 from selmf/new_qr_engine

New qr engine, part II
This commit is contained in:
Luis Ángel San Martín 2023-04-08 10:19:26 +02:00 committed by GitHub
commit e5026c02ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 80 additions and 140 deletions

View File

@ -7,9 +7,11 @@ Version counting is based on semantic versioning (Major.Feature.Patch)
### YACReaderLibrary ### YACReaderLibrary
* Fix scroll in grid views when using Qt6 builds. * Fix scroll in grid views when using Qt6 builds.
* Fix deleting metadata from comics also deleted the number of pages info. * Fix deleting metadata from comics also deleted the number of pages info.
* Use https://github.com/nayuki/QR-Code-generator instead of libqrencode for QR code generation
### Server ### Server
* New search API that exposes the search engine. * New search API that exposes the search engine.
* Print scannable QR code at server start
## 9.11 ## 9.11

View File

@ -12,11 +12,6 @@ DEFINES += YACREADER
include (../config.pri) include (../config.pri)
include (../dependencies/pdf_backend.pri) include (../dependencies/pdf_backend.pri)
unix:haiku {
DEFINES += _BSD_SOURCE
LIBS += -lnetwork -lbsd
}
CONFIG(force_angle) { CONFIG(force_angle) {
contains(QMAKE_TARGET.arch, x86_64) { contains(QMAKE_TARGET.arch, x86_64) {
Release:DESTDIR = ../release64_angle Release:DESTDIR = ../release64_angle

View File

@ -18,11 +18,6 @@ DEFINES += SERVER_RELEASE YACREADER_LIBRARY
include (../config.pri) include (../config.pri)
include (../dependencies/pdf_backend.pri) include (../dependencies/pdf_backend.pri)
unix:haiku {
DEFINES += _BSD_SOURCE
LIBS += -lnetwork -lbsd
}
INCLUDEPATH += ../common/gl INCLUDEPATH += ../common/gl
# there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based # there are two builds for Windows, Desktop OpenGL based and ANGLE OpenGL ES based
@ -155,7 +150,8 @@ HEADERS += comic_flow.h \
yacreader_comic_info_helper.h \ yacreader_comic_info_helper.h \
db/reading_list.h \ db/reading_list.h \
db/query_parser.h \ db/query_parser.h \
current_comic_view_helper.h current_comic_view_helper.h \
ip_config_helper.h
!CONFIG(no_opengl) { !CONFIG(no_opengl) {
HEADERS += ../common/gl/yacreader_flow_gl.h HEADERS += ../common/gl/yacreader_flow_gl.h
@ -237,7 +233,8 @@ SOURCES += comic_flow.cpp \
yacreader_comic_info_helper.cpp\ yacreader_comic_info_helper.cpp\
db/reading_list.cpp \ db/reading_list.cpp \
current_comic_view_helper.cpp \ current_comic_view_helper.cpp \
db/query_parser.cpp db/query_parser.cpp \
ip_config_helper.cpp
!CONFIG(no_opengl) { !CONFIG(no_opengl) {
SOURCES += ../common/gl/yacreader_flow_gl.cpp SOURCES += ../common/gl/yacreader_flow_gl.cpp

View File

@ -0,0 +1,33 @@
#include <QNetworkInterface>
#include "ip_config_helper.h"
#include "qnaturalsorting.h"
// 192.168 (most comon local subnet for ips are always put first)
// IPs are sorted using natoral sorting
QList<QString> getIpAddresses()
{
auto ipComparator = [](const QString &ip1, const QString &ip2) {
if (ip1.startsWith("192.168") && ip2.startsWith("192.168"))
return naturalSortLessThanCI(ip1, ip2);
if (ip1.startsWith("192.168"))
return true;
if (ip2.startsWith("192.168"))
return false;
return naturalSortLessThanCI(ip1, ip2);
};
QList<QString> addresses;
for (auto add : QNetworkInterface::allAddresses()) {
// Exclude loopback, local, multicast
if (add.isGlobal()) {
addresses.push_back(add.toString());
}
}
std::sort(addresses.begin(), addresses.end(), ipComparator);
return addresses;
}

View File

@ -0,0 +1,4 @@
#ifndef YR_IP_CONFIG_HELPER
#define YR_IP_CONFIG_HELPER
QList<QString> getIpAddresses();
#endif

View File

@ -1,85 +1,17 @@
#include "server_config_dialog.h"
#include <QCoreApplication>
#include <QGridLayout> #include <QGridLayout>
#include <QNetworkInterface>
#include <QHostInfo>
#include <QHostAddress>
#include <QSettings> #include <QSettings>
#include <QPalette> #include <QPalette>
#include <QIntValidator>
#include <QFormLayout>
#include <QBitmap> #include <QBitmap>
#include <QPainter> #include <QPainter>
#include <QPixmap> #include <QPixmap>
#include "server_config_dialog.h"
#include "yacreader_http_server.h" #include "yacreader_http_server.h"
#include "yacreader_global_gui.h" #include "yacreader_global_gui.h"
#include "qnaturalsorting.h" #include "ip_config_helper.h"
#include "qrcodegen.hpp" #include "qrcodegen.hpp"
#include <algorithm>
// 192.168 (most comon local subnet for ips are always put first)
// IPs are sorted using natoral sorting
bool ipComparator(const QString &ip1, const QString &ip2)
{
if (ip1.startsWith("192.168") && ip2.startsWith("192.168"))
return naturalSortLessThanCI(ip1, ip2);
if (ip1.startsWith("192.168"))
return true;
if (ip2.startsWith("192.168"))
return false;
return naturalSortLessThanCI(ip1, ip2);
}
#ifndef Q_OS_WIN32
#include <sys/types.h>
#include <ifaddrs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
QList<QString> addresses()
{
struct ifaddrs *ifAddrStruct = NULL;
struct ifaddrs *ifa = NULL;
void *tmpAddrPtr = NULL;
QList<QString> localAddreses;
getifaddrs(&ifAddrStruct);
for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr) {
if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4
// is a valid IP4 Address
tmpAddrPtr = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
char addressBuffer[INET_ADDRSTRLEN];
inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
localAddreses.push_back(QString(addressBuffer));
// printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
} else if (ifa->ifa_addr->sa_family == AF_INET6) { // check it is IP6
// is a valid IP6 Address
tmpAddrPtr = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
char addressBuffer[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
// printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
}
}
}
if (ifAddrStruct != NULL)
freeifaddrs(ifAddrStruct);
return localAddreses;
}
#endif
extern YACReaderHttpServer *httpServer; extern YACReaderHttpServer *httpServer;
ServerConfigDialog::ServerConfigDialog(QWidget *parent) ServerConfigDialog::ServerConfigDialog(QWidget *parent)
@ -224,47 +156,11 @@ void ServerConfigDialog::enableperformanceWorkaround(int status)
void ServerConfigDialog::generateQR() void ServerConfigDialog::generateQR()
{ {
ip->clear(); ip->clear();
QString dir;
#ifdef Q_OS_WIN32 auto addresses = getIpAddresses();
QList<QHostAddress> list = QHostInfo::fromName(QHostInfo::localHostName()).addresses(); if (addresses.length() > 0) {
generateQR(addresses.first() + ":" + httpServer->getPort());
QList<QString> otherAddresses; ip->addItems(addresses);
foreach (QHostAddress add, list) {
QString tmp = add.toString();
if (tmp.contains(".") && !tmp.startsWith("127")) {
otherAddresses.push_back(tmp);
}
}
#else
QList<QString> list = addresses();
QList<QString> otherAddresses;
foreach (QString add, list) {
QString tmp = add;
if (tmp.contains(".") && !tmp.startsWith("127")) {
otherAddresses.push_back(tmp);
}
}
#endif
std::sort(otherAddresses.begin(), otherAddresses.end(), ipComparator);
if (!otherAddresses.isEmpty()) {
dir = otherAddresses.first();
otherAddresses.pop_front();
}
if (otherAddresses.length() > 0 || !dir.isEmpty()) {
if (!dir.isEmpty()) {
generateQR(dir + ":" + httpServer->getPort());
ip->addItem(dir);
} else {
generateQR(otherAddresses.first() + ":" + httpServer->getPort());
}
ip->addItems(otherAddresses);
port->setText(httpServer->getPort()); port->setText(httpServer->getPort());
} }
} }

View File

@ -15,6 +15,7 @@ DEFINES += SERVER_RELEASE YACREADER_LIBRARY
# do a basic dependency check # do a basic dependency check
include(headless_config.pri) include(headless_config.pri)
include(../dependencies/pdf_backend.pri) include(../dependencies/pdf_backend.pri)
include(../third_party/QrCode/QrCode.pri)
greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat greaterThan(QT_MAJOR_VERSION, 5): QT += core5compat
@ -32,11 +33,6 @@ macx {
CONFIG += objective_c CONFIG += objective_c
} }
unix:haiku {
DEFINES += _BSD_SOURCE
LIBS += -lnetwork -lbsd
}
#CONFIG += release #CONFIG += release
CONFIG -= flat CONFIG -= flat
QT += core sql network QT += core sql network
@ -67,6 +63,7 @@ HEADERS += ../YACReaderLibrary/library_creator.h \
../YACReaderLibrary/comic_files_manager.h \ ../YACReaderLibrary/comic_files_manager.h \
console_ui_library_creator.h \ console_ui_library_creator.h \
libraries_updater.h \ libraries_updater.h \
../YACReaderLibrary/ip_config_helper.h \
../YACReaderLibrary/db/query_lexer.h \ ../YACReaderLibrary/db/query_lexer.h \
../YACReaderLibrary/db/query_parser.h \ ../YACReaderLibrary/db/query_parser.h \
../YACReaderLibrary/db/search_query.h ../YACReaderLibrary/db/search_query.h
@ -95,6 +92,7 @@ SOURCES += ../YACReaderLibrary/library_creator.cpp \
console_ui_library_creator.cpp \ console_ui_library_creator.cpp \
main.cpp \ main.cpp \
libraries_updater.cpp \ libraries_updater.cpp \
../YACReaderLibrary/ip_config_helper.cpp \
../YACReaderLibrary/db/query_lexer.cpp \ ../YACReaderLibrary/db/query_lexer.cpp \
../YACReaderLibrary/db/query_parser.cpp \ ../YACReaderLibrary/db/query_parser.cpp \
../YACReaderLibrary/db/search_query.cpp \ ../YACReaderLibrary/db/search_query.cpp \

View File

@ -1,4 +1,3 @@
// #include <QtCore>
#include <QCoreApplication> #include <QCoreApplication>
#include <QSysInfo> #include <QSysInfo>
#include <QDir> #include <QDir>
@ -20,6 +19,8 @@
#include "QsLog.h" #include "QsLog.h"
#include "QsLogDest.h" #include "QsLogDest.h"
#include "qrcodegen.hpp"
#include "ip_config_helper.h"
using namespace QsLogging; using namespace QsLogging;
// Returns false in case of a parse error (unknown option or missing value); returns true otherwise. // Returns false in case of a parse error (unknown option or missing value); returns true otherwise.
@ -29,17 +30,6 @@ void logSystemAndConfig()
QLOG_INFO() << "---------- System & configuration ----------"; QLOG_INFO() << "---------- System & configuration ----------";
QLOG_INFO() << "OS:" << QSysInfo::prettyProductName() << "Version: " << QSysInfo::productVersion(); QLOG_INFO() << "OS:" << QSysInfo::prettyProductName() << "Version: " << QSysInfo::productVersion();
QLOG_INFO() << "Kernel:" << QSysInfo::kernelType() << QSysInfo::kernelVersion() << "Architecture:" << QSysInfo::currentCpuArchitecture(); QLOG_INFO() << "Kernel:" << QSysInfo::kernelType() << QSysInfo::kernelVersion() << "Architecture:" << QSysInfo::currentCpuArchitecture();
/* TODO: qrencode could be helpfull for showing a qr code in the web client for client devices
#if defined Q_OS_UNIX && !defined Q_OS_MAC
if(QFileInfo(QString(BINDIR)+"/qrencode").exists())
#else
if(QFileInfo(QCoreApplication::applicationDirPath()+"/utils/qrencode.exe").exists() || QFileInfo("./util/qrencode").exists())
#endif
QLOG_INFO() << "qrencode : found";
else
QLOG_INFO() << "qrencode : not found";
*/
QLOG_INFO() << "Libraries: " << DBHelper::getLibraries().getLibraries(); QLOG_INFO() << "Libraries: " << DBHelper::getLibraries().getLibraries();
QLOG_INFO() << "--------------------------------------------"; QLOG_INFO() << "--------------------------------------------";
} }
@ -76,6 +66,31 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt
} }
} }
void printServerInfo(YACReaderHttpServer *httpServer)
{
auto addresses = getIpAddresses();
QLOG_INFO() << "Running on" << addresses.first() + ":" + httpServer->getPort().toLocal8Bit() << "\n";
qrcodegen::QrCode code = qrcodegen::QrCode::encodeText(
(addresses.first() + ":" + httpServer->getPort()).toLocal8Bit(),
qrcodegen::QrCode::Ecc::LOW);
int border = 4;
for (int y = -border; y < code.getSize() + border; y += 2) {
QString QRCodeString;
for (int x = -border - 1; x < code.getSize() + border + 1; x++) {
QRCodeString.append((code.getModule(x, y) && code.getModule(x, y + 1))
? " "
: code.getModule(x, y + 1) ? "\u2580"
: code.getModule(x, y) ? "\u2584"
: "\u2588");
}
QLOG_INFO() << QRCodeString;
}
if (addresses.length() > 1) {
QLOG_INFO() << addresses.length() - 1 << "more network interfaces detected";
}
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
qInstallMessageHandler(messageHandler); qInstallMessageHandler(messageHandler);
@ -215,7 +230,7 @@ int main(int argc, char **argv)
httpServer->start(); httpServer->start();
} }
QLOG_INFO() << "Running on port" << httpServer->getPort(); printServerInfo(httpServer);
// Update libraries to new versions // Update libraries to new versions
LibrariesUpdater updater; LibrariesUpdater updater;