From f4f1b53b9646288d73979f8339a90fbbbcb9eedc Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 16 Aug 2011 16:38:56 +0200 Subject: Move printing into it's own library Create a libQtPrintSupport library that contains our current printing infrastructure. Long term this will get replaced with a libQtPrint, as the current architecture is not really maintainable. Change-Id: I7362fff6786b58c5b4e9213c23eda36d15048aa2 Reviewed-on: http://codereview.qt.nokia.com/3209 Reviewed-by: Qt Sanity Bot Reviewed-by: Gunnar Sletta --- src/printsupport/dialogs/qpagesetupdialog_mac.mm | 315 +++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 src/printsupport/dialogs/qpagesetupdialog_mac.mm (limited to 'src/printsupport/dialogs/qpagesetupdialog_mac.mm') diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm new file mode 100644 index 0000000000..725520116a --- /dev/null +++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm @@ -0,0 +1,315 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpagesetupdialog.h" + +#include +#include +#include +#include + +#ifndef QT_NO_PRINTDIALOG + +QT_USE_NAMESPACE + +@class QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate); + +@interface QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) : NSObject { + QMacPrintEnginePrivate *pe; +} +- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine; +- (void)pageLayoutDidEnd:(NSPageLayout *)pageLayout + returnCode:(int)returnCode contextInfo:(void *)contextInfo; +@end + +@implementation QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) +- (id)initWithMacPrintEngine:(QMacPrintEnginePrivate *)printEngine +{ + self = [super init]; + if (self) { + pe = printEngine; + } + return self; + +} +- (void)pageLayoutDidEnd:(NSPageLayout *)pageLayout + returnCode:(int)returnCode contextInfo:(void *)contextInfo +{ + Q_UNUSED(pageLayout); + QPageSetupDialog *dialog = static_cast(contextInfo); + if (returnCode == NSOKButton) { + PMRect paperRect; + PMGetUnadjustedPaperRect(pe->format, &paperRect); + pe->customSize = QSizeF(paperRect.right - paperRect.left, + paperRect.bottom - paperRect.top); + } + 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) +#ifndef QT_MAC_USE_COCOA + ,upp(0) +#else + ,pageLayout(0) +#endif + {} + + ~QPageSetupDialogPrivate() { +#ifndef QT_MAC_USE_COCOA + if (upp) { + DisposePMSheetDoneUPP(upp); + upp = 0; + } + QHash::iterator it = sheetCallbackMap.begin(); + while (it != sheetCallbackMap.end()) { + if (it.value() == this) { + it = sheetCallbackMap.erase(it); + } else { + ++it; + } + } +#endif + } + +#ifndef QT_MAC_USE_COCOA + void openCarbonPageLayout(Qt::WindowModality modality); + void closeCarbonPageLayout(); + static void pageSetupDialogSheetDoneCallback(PMPrintSession printSession, WindowRef /*documentWindow*/, Boolean accepted) { + QPageSetupDialogPrivate *priv = sheetCallbackMap.value(printSession); + if (!priv) { + qWarning("%s:%d: QPageSetupDialog::exec: Could not retrieve data structure, " + "you most likely now have an infinite modal loop", __FILE__, __LINE__); + return; + } + priv->q_func()->done(accepted ? QDialog::Accepted : QDialog::Rejected); + } +#else + void openCocoaPageLayout(Qt::WindowModality modality); + void closeCocoaPageLayout(); +#endif + + QMacPrintEnginePrivate *ep; +#ifndef QT_MAC_USE_COCOA + PMSheetDoneUPP upp; + static QHash sheetCallbackMap; +#else + NSPageLayout *pageLayout; +#endif +}; + +#ifndef QT_MAC_USE_COCOA +QHash QPageSetupDialogPrivate::sheetCallbackMap; +void QPageSetupDialogPrivate::openCarbonPageLayout(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(); + + sheetCallbackMap.insert(ep->session, this); + if (modality == Qt::ApplicationModal) { + QWidget modal_widg(0, Qt::Window); + modal_widg.setObjectName(QLatin1String(__FILE__ "__modal_dlg")); + modal_widg.createWinId(); + QApplicationPrivate::enterModal(&modal_widg); + QApplicationPrivate::native_modal_dialog_active = true; + Boolean accepted; + PMSessionPageSetupDialog(ep->session, ep->format, &accepted); + QApplicationPrivate::leaveModal(&modal_widg); + QApplicationPrivate::native_modal_dialog_active = false; + pageSetupDialogSheetDoneCallback(ep->session, 0, accepted); + } else { + // Window Modal means that we use a sheet at the moment, there's no other way to do it correctly. + if (!upp) + upp = NewPMSheetDoneUPP(QPageSetupDialogPrivate::pageSetupDialogSheetDoneCallback); + PMSessionUseSheets(ep->session, qt_mac_window_for(q->parentWidget()), upp); + Boolean unused; + PMSessionPageSetupDialog(ep->session, ep->format, &unused); + } +} + +void QPageSetupDialogPrivate::closeCarbonPageLayout() +{ + // if the margins have changed, we have to use the margins from the new + // PMFormat object + if (q_func()->result() == QDialog::Accepted) { + PMPaper paper; + PMPaperMargins margins; + PMGetPageFormatPaper(ep->format, &paper); + PMPaperGetMargins(paper, &margins); + ep->leftMargin = margins.left; + ep->topMargin = margins.top; + ep->rightMargin = margins.right; + ep->bottomMargin = margins.bottom; + + PMRect paperRect; + PMGetUnadjustedPaperRect(ep->format, &paperRect); + ep->customSize = QSizeF(paperRect.right - paperRect.left, + paperRect.bottom - paperRect.top); + } + sheetCallbackMap.remove(ep->session); +} +#else +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(); + + 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]; + + if (modality == Qt::ApplicationModal) { + int rval = [pageLayout runModalWithPrintInfo:ep->printInfo]; + [delegate pageLayoutDidEnd:pageLayout returnCode:rval contextInfo:q]; + } else { + Q_ASSERT(q->parentWidget()); + [pageLayout beginSheetWithPrintInfo:ep->printInfo + modalForWindow:qt_mac_window_for(q->parentWidget()) + 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]); + + [pageLayout release]; + pageLayout = 0; +} +#endif + +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) +{ + Q_D(QPageSetupDialog); + + if (d->printer->outputFormat() != QPrinter::NativeFormat) + return; + +#ifndef QT_MAC_USE_COCOA + bool isCurrentlyVisible = d->sheetCallbackMap.contains(d->ep->session); +#else + bool isCurrentlyVisible = (d->pageLayout != 0); +#endif + if (!visible == !isCurrentlyVisible) + return; + + if (visible) { +#ifndef QT_MAC_USE_COCOA + d->openCarbonPageLayout(parentWidget() ? Qt::WindowModal + : Qt::ApplicationModal); +#else + d->openCocoaPageLayout(parentWidget() ? Qt::WindowModal + : Qt::ApplicationModal); +#endif + return; + } else { +#ifndef QT_MAC_USE_COCOA + d->closeCarbonPageLayout(); +#else + if (d->pageLayout) { + d->closeCocoaPageLayout(); + return; + } +#endif + } +} + +int QPageSetupDialog::exec() +{ + Q_D(QPageSetupDialog); + + if (d->printer->outputFormat() != QPrinter::NativeFormat) + return Rejected; + +#ifndef QT_MAC_USE_COCOA + d->openCarbonPageLayout(Qt::ApplicationModal); + d->closeCarbonPageLayout(); +#else + QMacCocoaAutoReleasePool pool; + d->openCocoaPageLayout(Qt::ApplicationModal); + d->closeCocoaPageLayout(); +#endif + return result(); +} + +QT_END_NAMESPACE + +#endif /* QT_NO_PRINTDIALOG */ -- cgit v1.2.3