From 088ae4ca71f54545a2a04da10a6e7cab4826db51 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 5 Mar 2012 15:01:55 +0100 Subject: Re-enable native print/pagesetup dialogs on Mac OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since QtPrintSupport does not have access to the internals of the print engine on Mac OS X (it lives in the platform plugin). We instead use the NSPrintInfoFromPrintEngine() invokable method in QPlatformNativeInterface to return an NSPrintInfo* that we can use where needed, or we use QPrintEngine::property()/setProperty() to communicate with the engine. This commit disables the generic UNIX dialogs and CUPS support on Mac OS X, ensuring that the default format on Mac OS X is the QPrinter::NativeFormat (previously qprinter.cpp would force PdfFormat as default on Q_OS_UNIX which is also defined on Mac OS X). The rest of the changes are straight forward porting. The methods: extern void macStartInterceptWindowTitle(QWidget *window); extern void macStopInterceptWindowTitle(); don't exist anymore, so don't use them. QMacCocoaAutoReleasePool also doens't work, so use NSAutoreleasePool directly. Change-Id: I341609e5efa53cadf8d174e4b282cbcae93e39e8 Reviewed-by: Morten Johan Sørvig --- src/printsupport/dialogs/dialogs.pri | 6 +- src/printsupport/dialogs/qpagesetupdialog.h | 2 +- src/printsupport/dialogs/qpagesetupdialog_mac.mm | 86 ++++++++-------- src/printsupport/dialogs/qprintdialog.h | 8 +- src/printsupport/dialogs/qprintdialog_mac.mm | 119 ++++++++++++----------- src/printsupport/kernel/kernel.pri | 4 +- src/printsupport/kernel/qprinter.cpp | 2 +- 7 files changed, 116 insertions(+), 111 deletions(-) (limited to 'src/printsupport') diff --git a/src/printsupport/dialogs/dialogs.pri b/src/printsupport/dialogs/dialogs.pri index 68b1737d73..2b92f43bec 100644 --- a/src/printsupport/dialogs/dialogs.pri +++ b/src/printsupport/dialogs/dialogs.pri @@ -9,10 +9,10 @@ HEADERS += \ dialogs/qprintdialog.h \ dialogs/qprintpreviewdialog.h -# ### fixme -false { +mac { OBJECTIVE_SOURCES += dialogs/qpagesetupdialog_mac.mm \ dialogs/qprintdialog_mac.mm + LIBS += -framework Cocoa } win32 { @@ -20,7 +20,7 @@ win32 { dialogs/qprintdialog_win.cpp } -unix { +unix:!mac { HEADERS += dialogs/qpagesetupdialog_unix_p.h SOURCES += dialogs/qprintdialog_unix.cpp \ dialogs/qpagesetupdialog_unix.cpp diff --git a/src/printsupport/dialogs/qpagesetupdialog.h b/src/printsupport/dialogs/qpagesetupdialog.h index 479332c097..466550b28b 100644 --- a/src/printsupport/dialogs/qpagesetupdialog.h +++ b/src/printsupport/dialogs/qpagesetupdialog.h @@ -83,7 +83,7 @@ public: void setOptions(PageSetupDialogOptions options); PageSetupDialogOptions options() const; -#if defined(Q_WS_MAC) || defined(Q_OS_WIN) +#if defined(Q_OS_MAC) || defined(Q_OS_WIN) virtual void setVisible(bool visible); #endif virtual int exec(); diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm index 3cd14489a3..6e4469e387 100644 --- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm +++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm @@ -39,12 +39,13 @@ ** ****************************************************************************/ +#include + #include "qpagesetupdialog.h" +#include "qabstractpagesetupdialog_p.h" -#include -#include -#include -#include +#include +#include #ifndef QT_NO_PRINTDIALOG @@ -52,20 +53,21 @@ QT_USE_NAMESPACE @class QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate); -@interface QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) : NSObject { - QMacPrintEnginePrivate *pe; +@interface QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) : NSObject +{ + NSPrintInfo *printInfo; } -- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine; +- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo; - (void)pageLayoutDidEnd:(NSPageLayout *)pageLayout returnCode:(int)returnCode contextInfo:(void *)contextInfo; @end @implementation QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) -- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine +- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo { self = [super init]; if (self) { - pe = printEngine; + printInfo = nsPrintInfo; } return self; @@ -75,29 +77,30 @@ QT_USE_NAMESPACE { Q_UNUSED(pageLayout); QPageSetupDialog *dialog = static_cast(contextInfo); + QPrinter *printer = dialog->printer(); + if (returnCode == NSOKButton) { + PMPageFormat format = static_cast([printInfo PMPageFormat]); PMRect paperRect; - PMGetUnadjustedPaperRect(pe->format, &paperRect); - pe->customSize = QSizeF(paperRect.right - paperRect.left, - paperRect.bottom - paperRect.top); + PMGetUnadjustedPaperRect(format, &paperRect); + QSizeF paperSize = QSizeF(paperRect.right - paperRect.left, paperRect.bottom - paperRect.top); + printer->printEngine()->setProperty(QPrintEngine::PPK_CustomPaperSize, paperSize); } + dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected); } @end QT_BEGIN_NAMESPACE -extern void macStartInterceptWindowTitle(QWidget *window); -extern void macStopInterceptWindowTitle(); - class QPageSetupDialogPrivate : public QAbstractPageSetupDialogPrivate { Q_DECLARE_PUBLIC(QPageSetupDialog) public: - QPageSetupDialogPrivate() : ep(0) - ,pageLayout(0) - {} + QPageSetupDialogPrivate() + : printInfo(0), pageLayout(0) + { } ~QPageSetupDialogPrivate() { } @@ -105,7 +108,7 @@ public: void openCocoaPageLayout(Qt::WindowModality modality); void closeCocoaPageLayout(); - QMacPrintEnginePrivate *ep; + NSPrintInfo *printInfo; NSPageLayout *pageLayout; }; @@ -113,56 +116,50 @@ void QPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality) { Q_Q(QPageSetupDialog); - // If someone is reusing a QPrinter object, the end released all our old - // information. In this case, we must reinitialize. - if (ep->session == 0) - ep->initialize(); + // get the NSPrintInfo from the print engine in the platform plugin + void *voidp = 0; + (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(), + "NSPrintInfoForPrintEngine", + Q_RETURN_ARG(void *, voidp), + Q_ARG(QPrintEngine *, printer->printEngine())); + printInfo = static_cast(voidp); + [printInfo retain]; - macStartInterceptWindowTitle(q); pageLayout = [NSPageLayout pageLayout]; // Keep a copy to this since we plan on using it for a bit. [pageLayout retain]; - QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) alloc] initWithMacPrintEngine:ep]; + QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) alloc] initWithNSPrintInfo:printInfo]; if (modality == Qt::ApplicationModal) { - int rval = [pageLayout runModalWithPrintInfo:ep->printInfo]; + int rval = [pageLayout runModalWithPrintInfo:printInfo]; [delegate pageLayoutDidEnd:pageLayout returnCode:rval contextInfo:q]; } else { Q_ASSERT(q->parentWidget()); - [pageLayout beginSheetWithPrintInfo:ep->printInfo - modalForWindow:qt_mac_window_for(q->parentWidget()) + QWindow *parentWindow = q->parentWidget()->windowHandle(); + NSWindow *window = static_cast(qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parentWindow)); + [pageLayout beginSheetWithPrintInfo:printInfo + modalForWindow:window delegate:delegate didEndSelector:@selector(pageLayoutDidEnd:returnCode:contextInfo:) contextInfo:q]; } - - macStopInterceptWindowTitle(); } void QPageSetupDialogPrivate::closeCocoaPageLayout() { - // NSPageLayout can change the session behind our back and then our - // d->ep->session object will become a dangling pointer. Update it - // based on the "current" session - ep->session = static_cast([ep->printInfo PMPrintSession]); - + [printInfo release]; + printInfo = 0; [pageLayout release]; pageLayout = 0; } QPageSetupDialog::QPageSetupDialog(QPrinter *printer, QWidget *parent) : QAbstractPageSetupDialog(*(new QPageSetupDialogPrivate), printer, parent) -{ - Q_D(QPageSetupDialog); - d->ep = static_cast(d->printer->paintEngine())->d_func(); -} +{ } QPageSetupDialog::QPageSetupDialog(QWidget *parent) : QAbstractPageSetupDialog(*(new QPageSetupDialogPrivate), 0, parent) -{ - Q_D(QPageSetupDialog); - d->ep = static_cast(d->printer->paintEngine())->d_func(); -} +{ } void QPageSetupDialog::setVisible(bool visible) { @@ -194,9 +191,10 @@ int QPageSetupDialog::exec() if (d->printer->outputFormat() != QPrinter::NativeFormat) return Rejected; - QMacCocoaAutoReleasePool pool; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; d->openCocoaPageLayout(Qt::ApplicationModal); d->closeCocoaPageLayout(); + [pool release]; return result(); } diff --git a/src/printsupport/dialogs/qprintdialog.h b/src/printsupport/dialogs/qprintdialog.h index af39a90d73..1eeca111e0 100644 --- a/src/printsupport/dialogs/qprintdialog.h +++ b/src/printsupport/dialogs/qprintdialog.h @@ -55,7 +55,7 @@ class QPrintDialogPrivate; class QPushButton; class QPrinter; -#if defined (Q_OS_UNIX) +#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) class QUnixPrintWidgetPrivate; class Q_PRINTSUPPORT_EXPORT QUnixPrintWidget : public QWidget @@ -90,7 +90,7 @@ public: ~QPrintDialog(); int exec(); -#if defined (Q_OS_UNIX) +#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) virtual void accept(); #endif void done(int result); @@ -130,10 +130,10 @@ Q_SIGNALS: private: Q_PRIVATE_SLOT(d_func(), void _q_chbPrintLastFirstToggled(bool)) -#if defined (Q_OS_UNIX) +#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) Q_PRIVATE_SLOT(d_func(), void _q_collapseOrExpandDialog()) #endif -# if defined(Q_OS_UNIX) && !defined(QT_NO_MESSAGEBOX) +# if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_MESSAGEBOX) Q_PRIVATE_SLOT(d_func(), void _q_checkFields()) # endif friend class QUnixPrintWidget; diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm index 6a267d920b..417ae20f29 100644 --- a/src/printsupport/dialogs/qprintdialog_mac.mm +++ b/src/printsupport/dialogs/qprintdialog_mac.mm @@ -41,13 +41,16 @@ #ifndef QT_NO_PRINTDIALOG -#include +#include -#include -#include -#include -#include -#include +#include "qprintdialog.h" +#include "qabstractprintdialog_p.h" + +#include +#include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -56,12 +59,11 @@ class QPrintDialogPrivate : public QAbstractPrintDialogPrivate Q_DECLARE_PUBLIC(QPrintDialog) public: - QPrintDialogPrivate() : ep(0), printPanel(0) + QPrintDialogPrivate() : printInfo(0), printPanel(0) {} void openCocoaPrintPanel(Qt::WindowModality modality); void closeCocoaPrintPanel(); - void initBeforeRun(); inline QPrintDialog *printDialog() { return q_func(); } @@ -76,7 +78,7 @@ public: inline void _q_btnBrowseClicked() {} inline void _q_btnPropertiesClicked() {} - QMacPrintEnginePrivate *ep; + NSPrintInfo *printInfo; NSPrintPanel *printPanel; }; @@ -87,25 +89,38 @@ QT_USE_NAMESPACE @class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate); -@interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject { +@interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject +{ + NSPrintInfo *printInfo; } +- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo; - (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(int)returnCode contextInfo:(void *)contextInfo; @end @implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) +- (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo +{ + if (self = [super init]) { + printInfo = nsPrintInfo; + } + return self; +} - (void)printPanelDidEnd:(NSPrintPanel *)printPanel returnCode:(int)returnCode contextInfo:(void *)contextInfo { Q_UNUSED(printPanel); - QPrintDialogPrivate *d = static_cast(contextInfo); - QPrintDialog *dialog = d->printDialog(); + QPrintDialog *dialog = static_cast(contextInfo); + QPrinter *printer = dialog->printer(); if (returnCode == NSOKButton) { + PMPrintSession session = static_cast([printInfo PMPrintSession]); + PMPrintSettings settings = static_cast([printInfo PMPrintSettings]); + UInt32 frompage, topage; - PMGetFirstPage(d->ep->settings, &frompage); - PMGetLastPage(d->ep->settings, &topage); + PMGetFirstPage(settings, &frompage); + PMGetLastPage(settings, &topage); topage = qMin(UInt32(INT_MAX), topage); dialog->setFromTo(frompage, topage); @@ -128,22 +143,19 @@ QT_USE_NAMESPACE // If the user selected print to file, the session has been // changed behind our back and our d->ep->session object is a // dangling pointer. Update it based on the "current" session - d->ep->session = static_cast([d->ep->printInfo PMPrintSession]); - - PMSessionGetDestinationType(d->ep->session, d->ep->settings, &dest); + PMSessionGetDestinationType(session, settings, &dest); if (dest == kPMDestinationFile) { QCFType file; - PMSessionCopyDestinationLocation(d->ep->session, d->ep->settings, &file); + PMSessionCopyDestinationLocation(session, settings, &file); UInt8 localFile[2048]; // Assuming there's a POSIX file system here. CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile)); - d->ep->outputFilename - = QString::fromUtf8(reinterpret_cast(localFile)); + printer->setOutputFileName(QString::fromUtf8(reinterpret_cast(localFile))); } else { // Keep output format. QPrinter::OutputFormat format; - format = d->printer->outputFormat(); - d->printer->setOutputFileName(QString()); - d->printer->setOutputFormat(format); + format = printer->outputFormat(); + printer->setOutputFileName(QString()); + printer->setOutputFormat(format); } } @@ -151,38 +163,33 @@ QT_USE_NAMESPACE } @end - QT_BEGIN_NAMESPACE -extern void macStartInterceptWindowTitle(QWidget *window); -extern void macStopInterceptWindowTitle(); - - -void QPrintDialogPrivate::initBeforeRun() +void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality) { Q_Q(QPrintDialog); - // If someone is reusing a QPrinter object, the end released all our old - // information. In this case, we must reinitialize. - if (ep->session == 0) - ep->initialize(); + // get the NSPrintInfo from the print engine in the platform plugin + void *voidp = 0; + (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(), + "NSPrintInfoForPrintEngine", + Q_RETURN_ARG(void *, voidp), + Q_ARG(QPrintEngine *, printer->printEngine())); + printInfo = static_cast(voidp); + [printInfo retain]; // It seems the only way that PM lets you use all is if the minimum // for the page range is 1. This _kind of_ makes sense if you think about // it. However, calling PMSetFirstPage() or PMSetLastPage() always enforces // the range. - PMSetPageRange(ep->settings, q->minPage(), q->maxPage()); + // get print settings from the platform plugin + PMPrintSettings settings = static_cast([printInfo PMPrintSettings]); + PMSetPageRange(settings, q->minPage(), q->maxPage()); if (q->printRange() == QAbstractPrintDialog::PageRange) { - PMSetFirstPage(ep->settings, q->fromPage(), false); - PMSetLastPage(ep->settings, q->toPage(), false); + PMSetFirstPage(settings, q->fromPage(), false); + PMSetLastPage(settings, q->toPage(), false); } -} - -void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality) -{ - Q_Q(QPrintDialog); - - initBeforeRun(); + [printInfo updateFromPMPrintSettings]; QPrintDialog::PrintDialogOptions qtOptions = q->options(); NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies; @@ -192,30 +199,32 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality) macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory | NSPrintPanelShowsOrientation; - macStartInterceptWindowTitle(q); printPanel = [NSPrintPanel printPanel]; - QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init]; + [printPanel retain]; [printPanel setOptions:macOptions]; + QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init]; if (modality == Qt::ApplicationModal) { - int rval = [printPanel runModalWithPrintInfo:ep->printInfo]; + int rval = [printPanel runModalWithPrintInfo:printInfo]; [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:this]; } else { Q_ASSERT(q->parentWidget()); - NSWindow *windowRef = qt_mac_window_for(q->parentWidget()); - [printPanel beginSheetWithPrintInfo:ep->printInfo - modalForWindow:windowRef + QWindow *parentWindow = q->parentWidget()->windowHandle(); + NSWindow *window = static_cast(qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parentWindow)); + [printPanel beginSheetWithPrintInfo:printInfo + modalForWindow:window delegate:delegate didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:) contextInfo:this]; } - - macStopInterceptWindowTitle(); } void QPrintDialogPrivate::closeCocoaPrintPanel() { - // ### + [printInfo release]; + printInfo = 0; + [printPanel release]; + printPanel = 0; } static bool warnIfNotNative(QPrinter *printer) @@ -234,7 +243,6 @@ QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent) Q_D(QPrintDialog); if (!warnIfNotNative(d->printer)) return; - d->ep = static_cast(d->printer->paintEngine())->d_func(); } QPrintDialog::QPrintDialog(QWidget *parent) @@ -243,7 +251,6 @@ QPrintDialog::QPrintDialog(QWidget *parent) Q_D(QPrintDialog); if (!warnIfNotNative(d->printer)) return; - d->ep = static_cast(d->printer->paintEngine())->d_func(); } QPrintDialog::~QPrintDialog() @@ -256,10 +263,10 @@ int QPrintDialog::exec() if (!warnIfNotNative(d->printer)) return QDialog::Rejected; - QMacCocoaAutoReleasePool pool; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; d->openCocoaPrintPanel(Qt::ApplicationModal); d->closeCocoaPrintPanel(); + [pool release]; return result(); } diff --git a/src/printsupport/kernel/kernel.pri b/src/printsupport/kernel/kernel.pri index e2fcd8d1dd..d7c9f56545 100644 --- a/src/printsupport/kernel/kernel.pri +++ b/src/printsupport/kernel/kernel.pri @@ -18,7 +18,7 @@ SOURCES += \ $$PWD/qplatformprintplugin.cpp \ $$PWD/qplatformprintersupport_qpa.cpp -unix { +unix:!mac { HEADERS += \ $$PWD/qprinterinfo_unix_p.h SOURCES += \ @@ -33,7 +33,7 @@ win32 { LIBS += -lWinspool -lComdlg32 } -win32 { +mac|win32 { DEFINES += QT_NO_CUPS QT_NO_LPR } else { SOURCES += $$PWD/qcups.cpp diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 85dc59ff34..404f45d509 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -155,7 +155,7 @@ Q_PRINTSUPPORT_EXPORT QSizeF qt_printerPaperSize(QPrinter::Orientation orientati void QPrinterPrivate::createDefaultEngines() { QPrinter::OutputFormat realOutputFormat = outputFormat; -#if defined (Q_OS_UNIX) +#if defined (Q_OS_UNIX) && !defined(Q_OS_MAC) if(outputFormat == QPrinter::NativeFormat) { realOutputFormat = QPrinter::PdfFormat; } -- cgit v1.2.3