mirror of
https://github.com/ONLYOFFICE/desktop-apps.git
synced 2026-02-10 18:05:16 +08:00
[win-linux] for bug 66375
This commit is contained in:
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user