[win-linux] for bug 66375

This commit is contained in:
SimplestStudio
2025-02-12 13:53:03 +02:00
parent 8aa3093d19
commit 41ebb67fbf
6 changed files with 219 additions and 50 deletions

View File

@ -233,7 +233,7 @@ core_linux {
CONFIG += link_pkgconfig
PKGCONFIG += glib-2.0 gtk+-3.0 atk gtk+-unix-print-3.0 xcb
LIBS += -lX11 -lX11-xcb
LIBS += -lX11 -lX11-xcb -lcups
cef_version_107 {
LIBS += $$PWD/../../build_tools/tools/linux/sysroot/ubuntu14/libdbus-1.so.3

View File

@ -1095,6 +1095,22 @@ void CAscApplicationManagerWrapper::onDocumentReady(int uid)
#ifdef _WIN32
Association::instance().chekForAssociations(uid);
#endif
if (uid > -1 && printData().printerCapabilitiesReady())
AscAppManager::sendCommandTo(GetViewById(uid), L"printer:config", printData().getPrinterCapabilitiesJson().toStdWString());
static bool check_printers = false;
if (!check_printers) {
check_printers = true;
printData().queryPrinterCapabilitiesAsync([=](const QString &json) {
// qDebug().noquote() << json;
for (int _uid : GetViewsId()) {
if (_uid > -1)
AscAppManager::sendCommandTo(GetViewById(_uid), L"printer:config", json.toStdWString());
}
});
}
}
void CAscApplicationManagerWrapper::startApp()

View File

@ -33,13 +33,21 @@
#include "cprintdata.h"
#include "utils.h"
#include "defines.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QRegularExpression>
#include <QSettings>
#include <future>
#include <cmath>
#ifdef __linux__
# include <cups/cups.h>
# include <cups/ppd.h>
#endif
class CPrintData::CPrintDataPrivate
class CPrintData::CPrintDataPrivate : public QObject
{
Q_OBJECT
public:
QPrinterInfo printer_info;
QPrintDialog::PrintRange print_range{QPrintDialog::PrintRange::AllPages};
@ -53,8 +61,11 @@ public:
int paper_width = 0,
paper_height = 0;
QString size_preset;
QString printers_capabilities_json;
int sender_id = -1;
int copies_count = 1;
FnVoidStr m_query_callback = nullptr;
std::future<void> m_future;
auto parseJsonOptions(const std::wstring& json) -> bool {
QJsonObject jsonOptions = Utils::parseJsonString(json);
@ -142,6 +153,109 @@ public:
parseJsonOptions(data->get_Options());
}
auto getPrintersCapabilitiesJson() const -> QString
{
QJsonArray printersArray;
#ifdef _WIN32
DWORD need = 0, ret = 0;
EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 2, nullptr, 0, &need, &ret);
std::vector<BYTE> buf(need);
if (EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 2, buf.data(), need, &need, &ret)) {
PRINTER_INFO_2 *printers = reinterpret_cast<PRINTER_INFO_2*>(buf.data());
for (DWORD i = 0; i < ret; ++i) {
LPDEVMODE pDevMode = printers[i].pDevMode;
bool duplex_supported = (pDevMode && (pDevMode->dmFields & DM_DUPLEX));
QJsonObject printerObject;
printerObject["name"] = QString::fromWCharArray(printers[i].pPrinterName);
printerObject["duplex_supported"] = duplex_supported;
constexpr int PAPER_NAME_LENGTH = 64;
bool paperNamesSuccess = false, paperSizeSuccess = false;
std::vector<WCHAR> paperNames;
std::vector<POINT> paperSize;
int paperNamesCount = DeviceCapabilities(printers[i].pPrinterName, printers[i].pPortName, DC_PAPERNAMES, NULL, NULL);
if (paperNamesCount > 0) {
paperNames.assign(paperNamesCount * PAPER_NAME_LENGTH, L'\0');
int res = DeviceCapabilities(printers[i].pPrinterName, printers[i].pPortName, DC_PAPERNAMES, paperNames.data(), NULL);
if (res == paperNamesCount)
paperNamesSuccess = true;
}
int paperSizeCount = DeviceCapabilities(printers[i].pPrinterName, printers[i].pPortName, DC_PAPERSIZE, NULL, NULL);
if (paperSizeCount > 0) {
paperSize.assign(paperSizeCount, {0, 0});
int res = DeviceCapabilities(printers[i].pPrinterName, printers[i].pPortName, DC_PAPERSIZE, (LPWSTR)paperSize.data(), NULL);
if (res == paperSizeCount)
paperSizeSuccess = true;
}
if (paperNamesSuccess && paperSizeSuccess && paperNamesCount == paperSizeCount) {
QJsonArray paperArray;
for (int j = 0; j < paperNamesCount; ++j) {
if (paperSize[j].x > 0 && paperSize[j].y > 0) {
std::wstring paperName(&paperNames[j * PAPER_NAME_LENGTH], PAPER_NAME_LENGTH);
QJsonObject paperObj;
paperObj["name"] = QString::fromWCharArray(paperName.c_str());
paperObj["width"] = (double)paperSize[j].x/10;
paperObj["height"] = (double)paperSize[j].y/10;
paperArray.append(paperObj);
}
}
printerObject["paper_supported"] = paperArray;
}
printersArray.append(printerObject);
}
}
#else
cups_dest_t *dests = nullptr;
int num_dests = cupsGetDests(&dests);
if (dests) {
for (int i = 0; i < num_dests; i++) {
cups_dest_t *dest = &dests[i];
const char *ppd = cupsGetPPD(dest->name);
ppd_file_t *ppdF = ppdOpenFile(ppd);
bool duplex_supported = ppdFindOption(ppdF, "Duplex");
QJsonObject printerObject;
printerObject["name"] = QString::fromUtf8(dest->name);
printerObject["duplex_supported"] = duplex_supported;
ppd_option_t *option = ppdFirstOption(ppdF);
while (option) {
if (strcmp(option->keyword, "PageSize") == 0) {
QJsonArray paperArray;
for (int j = 0; j < option->num_choices; j++) {
if (strcmp(option->choices[j].choice, "Custom") != 0) {
if (ppd_size_t *size = ppdPageSize(ppdF, option->choices[j].choice)) {
QJsonObject paperObj;
paperObj["name"] = QString::fromUtf8(option->choices[j].choice);
paperObj["width"] = qRound(25.4 * size->width / 72.0);
paperObj["height"] = qRound(25.4 * size->length / 72.0);
paperArray.append(paperObj);
}
}
}
printerObject["paper_supported"] = paperArray;
}
option = ppdNextOption(ppdF);
}
printersArray.append(printerObject);
ppdClose(ppdF);
}
cupsFreeDests(num_dests, dests);
}
#endif
QJsonObject rootObject;
rootObject["printers"] = printersArray;
return QJsonDocument(rootObject).toJson(QJsonDocument::Indented);
}
public slots:
void onPrinterCapabilitiesReady(QString json)
{
printers_capabilities_json = json;
if (m_query_callback)
m_query_callback(json);
}
};
CPrintData::CPrintData()
@ -152,6 +266,8 @@ CPrintData::CPrintData()
CPrintData::~CPrintData()
{
if (m_priv->m_future.valid())
m_priv->m_future.wait();
delete m_priv, m_priv = nullptr;
}
@ -287,3 +403,24 @@ auto CPrintData::duplexMode() const -> QPrinter::DuplexMode
{
return m_priv->duplex_mode;
}
bool CPrintData::printerCapabilitiesReady() const
{
return !m_priv->printers_capabilities_json.isEmpty();
}
QString CPrintData::getPrinterCapabilitiesJson() const
{
return m_priv->printers_capabilities_json;
}
auto CPrintData::queryPrinterCapabilitiesAsync(const FnVoidStr &callback) const -> void
{
m_priv->m_query_callback = callback;
m_priv->m_future = std::async(std::launch::async, [=]() {
QString json = m_priv->getPrintersCapabilitiesJson();
QMetaObject::invokeMethod(m_priv, "onPrinterCapabilitiesReady", Qt::QueuedConnection, Q_ARG(QString, json));
});
}
#include "cprintdata.moc"

View File

@ -36,6 +36,10 @@
#include "applicationmanager_events.h"
#include <QPrinterInfo>
#include <QPrintDialog>
#include <functional>
typedef std::function<void(const QString&)> FnVoidStr;
class CPrintData
{
@ -59,6 +63,9 @@ public:
auto viewId() const -> int;
auto copiesCount() const -> int;
auto duplexMode() const -> QPrinter::DuplexMode;
auto printerCapabilitiesReady() const -> bool;
auto getPrinterCapabilitiesJson() const -> QString;
auto queryPrinterCapabilitiesAsync(const FnVoidStr &callback) const -> void;
private:
class CPrintDataPrivate;

View File

@ -122,44 +122,22 @@ static GtkPageRange *get_page_ranges(GtkEntry *entry, gint *num_ranges)
return NULL;
}
auto gtkPaperNameFromPageSize(PageSize page_size)->QString
auto gtkPaperNameFromPageSize(const QSizeF &size)->QString
{
switch (page_size) {
case PageSize::A0:
return "iso_a0";
case PageSize::A1:
return "iso_a1";
case PageSize::A2:
return "iso_a2";
case PageSize::A3:
return "iso_a3";
case PageSize::A4:
return "iso_a4";
case PageSize::A5:
return "iso_a5";
case PageSize::A6:
return "iso_a6";
case PageSize::B5:
return "ppd_EnvB5"; // "iso_b5" - not working
case PageSize::Tabloid:
return "na_ledger";
case PageSize::EnvelopeDL:
return "iso_dl";
case PageSize::Comm10E:
return "na_number-10";
case PageSize::SuperB:
return "na_super-b";
// case PageSize::TabloidExtra:
// return "na_ledger";
case PageSize::Letter:
return "na_letter";
case PageSize::Legal:
return "na_legal";
case PageSize::EnvelopeChou3:
return "jpn_chou3";
default:
return QPageSize::name((QPageSize::PageSizeId)page_size);
QString gtkPaperName;
constexpr double diff = 1.0;
GList *paper_sizes = gtk_paper_size_get_paper_sizes(FALSE);
for (GList *it = paper_sizes; it != nullptr; it = it->next) {
GtkPaperSize *psize = (GtkPaperSize*)it->data;
double width = gtk_paper_size_get_width(psize, GTK_UNIT_MM);
double height = gtk_paper_size_get_height(psize, GTK_UNIT_MM);
if (std::abs(size.width() - width) < diff && std::abs(size.height() - height) < diff) {
gtkPaperName = gtk_paper_size_get_name(psize);
break;
}
}
g_list_free_full(paper_sizes, (GDestroyNotify)gtk_paper_size_free);
return gtkPaperName;
}
GtkPrintDialog::GtkPrintDialog(QPrinter *printer, QWidget *parent) :
@ -342,8 +320,8 @@ QDialog::DialogCode GtkPrintDialog::exec()
gtk_page_setup_set_bottom_margin(page_setup, bottom_in, unit);
QPageSize ps = m_printer->pageLayout().pageSize();
QSize page_size = ps.size(QPageSize::Millimeter).toSize();
const QString paper_name = gtkPaperNameFromPageSize(m_printer->pageSize());
QSizeF page_size = ps.size(QPageSize::Millimeter);
const QString paper_name = gtkPaperNameFromPageSize(page_size);
GtkPaperSize *psize = gtk_paper_size_new_custom(
paper_name.toUtf8().data(),
ps.name().toUtf8().data(),

View File

@ -45,9 +45,9 @@
typedef QPageSize::PageSizeId PageSize;
auto getPaperSizeFromPageSize(PageSize page_size)->int
auto getPaperSizeFromPageSize(LPWSTR pPrinterName, const QPageSize &ps)->int
{
switch (page_size) {
switch (ps.id()) {
// case PageSize::A0:
// return DMPAPER_USER;
// case PageSize::A1:
@ -80,9 +80,37 @@ auto getPaperSizeFromPageSize(PageSize page_size)->int
return DMPAPER_LEGAL;
case PageSize::EnvelopeChou3:
return DMPAPER_JENV_CHOU3;
default:
default: {
bool paperNamesSuccess = false, paperSizeSuccess = false;
std::vector<WORD> papers;
std::vector<POINT> paperSize;
int papersCount = DeviceCapabilities(pPrinterName, NULL, DC_PAPERS, NULL, NULL);
if (papersCount > 0) {
papers.assign(papersCount, 0);
int res = DeviceCapabilities(pPrinterName, NULL, DC_PAPERS, (LPWSTR)papers.data(), NULL);
if (res == papersCount)
paperNamesSuccess = true;
}
int paperSizeCount = DeviceCapabilities(pPrinterName, NULL, DC_PAPERSIZE, NULL, NULL);
if (paperSizeCount > 0) {
paperSize.assign(paperSizeCount, {0, 0});
int res = DeviceCapabilities(pPrinterName, NULL, DC_PAPERSIZE, (LPWSTR)paperSize.data(), NULL);
if (res == paperSizeCount)
paperSizeSuccess = true;
}
if (paperNamesSuccess && paperSizeSuccess && papersCount == paperSizeCount) {
constexpr double diff = 1.0;
QSizeF size = ps.size(QPageSize::Millimeter);
for (int j = 0; j < papersCount; ++j) {
double width = (double)paperSize[j].x/10;
double height = (double)paperSize[j].y/10;
if (std::abs(size.width() - width) < diff && std::abs(size.height() - height) < diff)
return papers[j];
}
}
return DMPAPER_USER;
}
}
}
#ifndef __OS_WIN_XP
@ -337,15 +365,18 @@ QDialog::DialogCode PrintDialog::exec()
(qt_duplex == QPrinter::DuplexShortSide) ? DMDUP_HORIZONTAL : DMDUP_SIMPLEX;
}
int paper_size = getPaperSizeFromPageSize(pPrinterName, m_printer->pageLayout().pageSize());
if (pDevMode->dmFields & DM_PAPERSIZE)
pDevMode->dmPaperSize = getPaperSizeFromPageSize(m_printer->pageLayout().pageSize().id());
pDevMode->dmPaperSize = paper_size;
QPageSize ps = m_printer->pageLayout().pageSize();
QSizeF page_size = ps.size(QPageSize::Millimeter);
if (pDevMode->dmFields & DM_PAPERWIDTH)
pDevMode->dmPaperWidth = qRound(10 * page_size.width());
if (pDevMode->dmFields & DM_PAPERLENGTH)
pDevMode->dmPaperLength = qRound(10 * page_size.height());
if (paper_size == DMPAPER_USER || !(pDevMode->dmFields & DM_PAPERSIZE)) {
QPageSize ps = m_printer->pageLayout().pageSize();
QSizeF page_size = ps.size(QPageSize::Millimeter);
if (pDevMode->dmFields & DM_PAPERWIDTH)
pDevMode->dmPaperWidth = qRound(10 * page_size.width());
if (pDevMode->dmFields & DM_PAPERLENGTH)
pDevMode->dmPaperLength = qRound(10 * page_size.height());
}
dwRet = DocumentProperties(parent_hwnd, hPrinter, pPrinterName, pDevMode, pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
}