[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-core-devel
Subject:    Printing: KPrintPreview
From:       Alex Merry <huntedhacker () tiscali ! co ! uk>
Date:       2007-09-24 15:10:44
Message-ID: 200709241610.49044.huntedhacker () tiscali ! co ! uk
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


I have here a working KPrintPreview class.  It's a KDialog, and is used 
as follows:

QPrinter printer;
KPrintPreview preview(&printer, this); // where "this" is a QWidget
doSomePrinting(printer);
preview.exec();

Basically, you use it almost identically to a QPrintDialog, except that 
you exec() the dialog after you've done the printing rather than 
before.

It uses any available KPart that advertises that it can deal with 
application/pdf (eg: Okular).  Note that I had to delete the kghostview 
desktop file to make this work, since kghostview is broken for me.

It was quite straightforward to adapt kolourpaint to use QPrinter and 
KPrintPreview, for testing.

I temporarily named the library kdeprint2, so as not to interfere with 
kdeprint.

Attached are a patch for kdelibs and the modifications I made to get 
kolourpaint to work.

Obviously the class could be made better in various ways, but it 
demonstrates a working print preview and an API for it.

Alex


PS: please keep discussions about the printing dialog in a separate 
thread, unless they directly relate to print preview.


-- 
KDE: http://www.kde.org
Ubuntu/Kubuntu: http://www.ubuntu.org http://www.kubuntu.org

["kolourpaint-kdeprint2.diff" (text/x-diff)]

Index: mainWindow/kpMainWindow_File.cpp
===================================================================
--- mainWindow/kpMainWindow_File.cpp	(revision 716349)
+++ mainWindow/kpMainWindow_File.cpp	(working copy)
@@ -37,6 +37,8 @@
 #include <qpixmap.h>
 #include <qsize.h>
 #include <QtDBus>
+#include <QPrinter>
+#include <QPrintDialog>
 
 #include <kapplication.h>
 #include <kaction.h>
@@ -52,7 +54,7 @@
 #include <kio/netaccess.h>
 #include <klocale.h>
 #include <kmessagebox.h>
-#include <kprinter.h>
+#include <kdeprint2/kprintpreview.h>
 #include <krecentfilesaction.h>
 #include <kscan.h>
 #include <kstandardshortcut.h>
@@ -66,7 +68,9 @@
 #include <kpDocumentMetaInfoDialog.h>
 #include <kpDocumentSaveOptionsWidget.h>
 #include <kpPixmapFX.h>
+#if 0
 #include <kpPrintDialogPage.h>
+#endif
 #include <kpView.h>
 #include <kpViewManager.h>
 
@@ -1054,7 +1058,7 @@ bool kpMainWindow::slotReload ()
 
 
 // private
-void kpMainWindow::sendFilenameToPrinter (KPrinter *printer)
+void kpMainWindow::sendFilenameToPrinter (QPrinter &printer)
 {
     KUrl url = d->document->url ();
     if (!url.isEmpty ())
@@ -1069,22 +1073,19 @@ void kpMainWindow::sendFilenameToPrinter
             fileName.truncate (dot);
 
     #if DEBUG_KP_MAIN_WINDOW
-        kDebug () << "kpMainWindow::sendFilenameToPrinter() fileName="
+        kDebug () << "fileName="
                    << fileName
                    << " dir="
                    << url.directory ()
                    << endl;
     #endif
-        printer->setDocName (fileName);
-        printer->setDocFileName (fileName);
-        printer->setDocDirectory (url.directory ());
+        printer.setDocName (fileName);
     }
 }
 
 
 // private
-void kpMainWindow::sendImageToPrinter (KPrinter *printer,
-        bool showPrinterSetupDialog)
+void kpMainWindow::sendImageToPrinter (QPrinter &printer)
 {
     // Get image to be printed.
     kpImage image = d->document->imageWithSelection ();
@@ -1149,8 +1150,8 @@ void kpMainWindow::sendImageToPrinter (K
     //     m   m       m = margin
     //     m   m
     //     mmmmm
-    const int printerWidthMM = printer->widthMM ();
-    const int printerHeightMM = printer->heightMM ();
+    const int printerWidthMM = printer.widthMM ();
+    const int printerHeightMM = printer.heightMM ();
 #if DEBUG_KP_MAIN_WINDOW
     kDebug () << "\tprinter: widthMM=" << printerWidthMM
                << " heightMM=" << printerHeightMM
@@ -1229,21 +1230,11 @@ void kpMainWindow::sendImageToPrinter (K
     Q_ASSERT (dpiX == dpiY);
 
 
-    // QPrinter::setResolution() has to be called before QPrinter::setup().
-    printer->setResolution (qMax (1, qRound (dpiX)));
+    printer.setResolution (qMax (1, qRound (dpiX)));
 
 
     sendFilenameToPrinter (printer);
 
-    if (showPrinterSetupDialog)
-    {
-        // The user can mutate margins at their own risk in this dialog.
-        // It doesn't seem to affect the size of the page as reported
-        // by QPaintDeviceMetrics::{width,height}MM().  COMPAT: fix comment - no \
                more QPaintDeviceMetrics
-        if (!printer->setup (this))
-            return;
-    }
-
 
     double originX = 0, originY = 0;
 
@@ -1251,7 +1242,7 @@ void kpMainWindow::sendImageToPrinter (K
     //
     // Only call this method after the user has set the print options i.e.
     // after the print dialog ("printer->setup()") has been accepted.
-    if (kpPrintDialogPage::shouldPrintImageCenteredOnPage (printer))
+    /*if (kpPrintDialogPage::shouldPrintImageCenteredOnPage (printer))
     {
         originX =
             (printerWidthMM * dpiX / KP_MILLIMETERS_PER_INCH - image.width ())
@@ -1259,7 +1250,7 @@ void kpMainWindow::sendImageToPrinter (K
         originY =
             (printerHeightMM * dpiY / KP_MILLIMETERS_PER_INCH - image.height ())
                 / 2;
-    }
+    }*/
 
 #if DEBUG_KP_MAIN_WINDOW
     kDebug () << "\torigin: x=" << originX << " y=" << originY;
@@ -1268,7 +1259,7 @@ void kpMainWindow::sendImageToPrinter (K
 
     // Send image to printer.
     QPainter painter;
-    painter.begin (printer);
+    painter.begin (&printer);
     painter.drawPixmap (qRound (originX), qRound (originY), image);
     painter.end ();
 }
@@ -1279,10 +1270,12 @@ void kpMainWindow::slotPrint ()
 {
     toolEndShape ();
 
-    KPrinter printer;
-    printer.addDialogPage (new kpPrintDialogPage (this));
+    QPrinter printer;
+    //printer.addDialogPage (new kpPrintDialogPage (this));
+    QPrintDialog printDialog(&printer, this);
+    printDialog.exec();
 
-    sendImageToPrinter (&printer, true/*showPrinterSetupDialog*/);
+    sendImageToPrinter (printer);
 }
 
 // private slot
@@ -1293,12 +1286,13 @@ void kpMainWindow::slotPrintPreview ()
     // Do not specify "false" to KPrinter::<ctor>()'s "restore" arg,
     // since we want to use the same KPrinter::options(), set by
     // kpPrintDialogPage.
-    KPrinter printer;
+    QPrinter printer;
+
+    KPrintPreview preview(&printer, this);
 
-    // TODO: pass "this" as parent
-    printer.setPreviewOnly (true);
+    sendImageToPrinter (printer);
 
-    sendImageToPrinter (&printer, false/*don't showPrinterSetupDialog*/);
+    preview.exec();
 }
 
 
Index: mainWindow/kpMainWindow.h
===================================================================
--- mainWindow/kpMainWindow.h	(revision 716349)
+++ mainWindow/kpMainWindow.h	(working copy)
@@ -362,8 +362,8 @@ private slots:
     bool slotReload ();
 
 private:
-    void sendFilenameToPrinter (KPrinter *printer);
-    void sendImageToPrinter (KPrinter *printer, bool showPrinterSetupDialog);
+    void sendFilenameToPrinter (QPrinter &printer);
+    void sendImageToPrinter (QPrinter &printer);
 
 private slots:
     void slotPrint ();
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 716349)
+++ CMakeLists.txt	(working copy)
@@ -155,7 +155,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/imag
 ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/imagelib/transforms/kpTransformSkewDialog.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/kpColorSimilarityDialog.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/dialogs/kpDocumentSaveOptionsPreviewDialog.cpp
-${CMAKE_CURRENT_SOURCE_DIR}/dialogs/kpPrintDialogPage.cpp
+#${CMAKE_CURRENT_SOURCE_DIR}/dialogs/kpPrintDialogPage.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/document/kpDocument.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/document/kpDocument_Open.cpp
 ${CMAKE_CURRENT_SOURCE_DIR}/document/kpDocument_Save.cpp
@@ -332,7 +332,7 @@ set(kolourpaint_lgpl_SRCS
 
 kde4_add_library(kolourpaint_lgpl SHARED ${kolourpaint_lgpl_SRCS})
 
-target_link_libraries(kolourpaint_lgpl ${KDE4_KDEPRINT_LIBS})
+target_link_libraries(kolourpaint_lgpl ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} \
kdeprint2)  set_target_properties(kolourpaint_lgpl PROPERTIES VERSION \
${GENERIC_LIB_VERSION} SOVERSION ${GENERIC_LIB_SOVERSION})  
 install(TARGETS kolourpaint_lgpl DESTINATION ${LIB_INSTALL_DIR})


["kdeprint2.diff" (text/x-diff)]

Index: kdeprint2/kprintpreview.h
===================================================================
--- kdeprint2/kprintpreview.h	(revision 0)
+++ kdeprint2/kprintpreview.h	(revision 0)
@@ -0,0 +1,45 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (c) 2007 Alex Merry <huntedhacker@tiscali.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License version 2 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ **/
+
+#ifndef KPRINTPREVIEW_H
+#define KPRINTPREVIEW_H
+
+#include <kdeprint2/kdeprint2_export.h>
+
+#include <kdialog.h>
+
+class KPrintPreviewPrivate;
+
+class KDEPRINT2_EXPORT KPrintPreview : public KDialog
+{
+    Q_OBJECT
+
+public:
+    explicit KPrintPreview(QPrinter *printer, QWidget *parent = 0);
+    virtual ~KPrintPreview();
+
+    void showEvent(QShowEvent *event);
+
+private:
+    KPrintPreviewPrivate * const d;
+};
+
+
+#endif // KPRINTPREVIEW_H
+
Index: kdeprint2/kdeprint2_export.h
===================================================================
--- kdeprint2/kdeprint2_export.h	(revision 0)
+++ kdeprint2/kdeprint2_export.h	(revision 0)
@@ -0,0 +1,46 @@
+/*  This file is part of the KDE project
+    Copyright (C) 2007 David Faure <faure@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KDEPRINT2_EXPORT_H
+#define KDEPRINT2_EXPORT_H
+
+/* needed for KDE_EXPORT and KDE_IMPORT macros */
+#include <kdemacros.h>
+
+#ifndef KDEPRINT2_EXPORT
+# if defined(MAKE_KDEPRINT2_LIB)
+/* We are building this library */
+#  define KDEPRINT2_EXPORT KDE_EXPORT
+# else
+/* We are using this library */
+#  define KDEPRINT2_EXPORT KDE_IMPORT
+# endif
+#endif
+
+# ifndef KDEPRINT2_EXPORT_DEPRECATED
+#  define KDEPRINT2_EXPORT_DEPRECATED KDE_DEPRECATED KDEPRINT2_EXPORT
+# endif
+# ifndef KDEPRINT2_MANAGEMENT_EXPORT_DEPRECATED
+#  define KDEPRINT2_MANAGEMENT_EXPORT_DEPRECATED KDE_DEPRECATED \
KDEPRINT2_MANAGEMENT_EXPORT +# endif
+# ifndef KDEPRINT2_MANAGEMENT_MODULE_EXPORT_DEPRECATED
+#  define KDEPRINT2_MANAGEMENT_MODULE_EXPORT_DEPRECATED KDE_DEPRECATED \
KDEPRINT2_MANAGEMENT_MODULE_EXPORT +# endif
+
+#endif
Index: kdeprint2/kprintpreview.cpp
===================================================================
--- kdeprint2/kprintpreview.cpp	(revision 0)
+++ kdeprint2/kprintpreview.cpp	(revision 0)
@@ -0,0 +1,165 @@
+/*
+ *  This file is part of the KDE libraries
+ *  Copyright (c) 2007 Alex Merry <huntedhacker@tiscali.co.uk>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License version 2 as published by the Free Software Foundation.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ **/
+
+#include "kprintpreview.h"
+
+#include <QtCore/QFile>
+#include <QtGui/QLabel>
+#include <QtGui/QPrinter>
+#include <QtGui/QShowEvent>
+
+#include <kmimetypetrader.h>
+#include <kparts/part.h>
+#include <kpluginfactory.h>
+#include <kpluginloader.h>
+#include <kservice.h>
+#include <ktempdir.h>
+
+
+class KPrintPreviewPrivate
+{
+public:
+    KPrintPreviewPrivate(KPrintPreview *host, QPrinter * _printer)
+        : q(host)
+        , printer(_printer)
+        , mainWidget(new QWidget(host))
+        , previewPart(0)
+        , failMessage(0)
+    {
+        if ( tempdir.exists() ) {
+            filename = tempdir.name() + "print_preview.pdf";
+        } else {
+            // XXX: not portable!
+            kWarning() << "Failed to create temporary directory";
+            filename = "/dev/null";
+        }
+    }
+
+    void getPart();
+    bool doPreview();
+    void fail();
+
+    KPrintPreview *q;
+
+    QPrinter *printer;
+    QWidget *mainWidget;
+
+    KTempDir tempdir;
+    QString filename;
+
+    KParts::ReadOnlyPart *previewPart;
+    QWidget *failMessage;
+};
+
+void KPrintPreviewPrivate::getPart()
+{
+    if (previewPart) {
+        kDebug(500) << "already got a part";
+        return;
+    }
+    kDebug(500) << "querying trader for application/pdf service";
+
+    KPluginFactory *factory(0);
+    KService::List offers =
+        KMimeTypeTrader::self()->query("application/pdf", "KParts/ReadOnlyPart");
+
+    KService::List::ConstIterator it = offers.begin();
+    while (!factory && it != offers.end()) {
+        KPluginLoader loader(**it);
+        factory = loader.factory();
+        if (!factory) {
+            kDebug(500) << "Loading failed:" << loader.errorString();
+        }
+        ++it;
+    }
+    if (factory) {
+        kDebug(500) << "Trying to create a part";
+        previewPart = factory->create<KParts::ReadOnlyPart>(q, (QVariantList() << \
"Print/Preview")); +        if (!previewPart) {
+            kDebug(500) << "Part creation failed";
+        }
+    }
+}
+
+bool KPrintPreviewPrivate::doPreview()
+{
+    if (!QFile::exists(filename)) {
+        kWarning() << "Nothing was produced to be previewed";
+        return false;
+    }
+
+    getPart();
+    if (!previewPart) {
+        //TODO: error dialog
+        kWarning() << "Could not find a PDF viewer for the preview dialog";
+        fail();
+        return false;
+    } else {
+        q->setMainWidget(previewPart->widget());
+        return previewPart->openUrl(filename);
+    }
+}
+
+void KPrintPreviewPrivate::fail()
+{
+    if (!failMessage) {
+        failMessage = new QLabel(i18n("Could not load print preview part"), q);
+    }
+    q->setMainWidget(failMessage);
+}
+
+
+
+
+KPrintPreview::KPrintPreview(QPrinter *printer, QWidget *parent)
+    : KDialog(parent)
+    , d(new KPrintPreviewPrivate(this, printer))
+{
+    kDebug(500) << "kdeprint: creating preview dialog";
+
+    // Set up the dialog
+    setCaption(i18n("Print Preview"));
+    setButtons(KDialog::Close);
+
+    // Set up the printer
+    kDebug(500) << "Will print to" << d->filename;
+    printer->setOutputFileName(d->filename);
+}
+
+KPrintPreview::~KPrintPreview()
+{
+    delete d;
+}
+
+void KPrintPreview::showEvent(QShowEvent *event)
+{
+    if (!event->spontaneous()) {
+        // being shown for the first time
+        if (!d->doPreview()) {
+            event->accept();
+            return;
+        }
+    }
+    KDialog::showEvent(event);
+}
+
+#include "kprintpreview.moc"
+
+
+
Index: kdeprint2/CMakeLists.txt
===================================================================
--- kdeprint2/CMakeLists.txt	(revision 0)
+++ kdeprint2/CMakeLists.txt	(revision 0)
@@ -0,0 +1,32 @@
+project(kdeprint2)
+
+
+set(kdeprint2_LIB_SRCS
+   kprintpreview.cpp
+)
+
+include_directories(${KDE4_KDEUI_INCLUDES} ${KDE4_KPARTS_INCLUDES})
+
+
+kde4_add_library(kdeprint2 SHARED ${kdeprint2_LIB_SRCS})
+
+target_link_libraries(kdeprint2 ${KDE4_KDEUI_LIBS} ${KDE4_KPARTS_LIBS} )
+
+set_target_properties(kdeprint2 PROPERTIES VERSION ${KDE_NON_GENERIC_LIB_VERSION} \
SOVERSION ${KDE_NON_GENERIC_LIB_SOVERSION} ) +install(TARGETS kdeprint2
+             RUNTIME DESTINATION ${BIN_INSTALL_DIR}
+             LIBRARY DESTINATION ${LIB_INSTALL_DIR}
+             ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
+)
+
+########### install files ###############
+
+install( FILES
+   kprintpreview.h
+   kdeprint2_export.h
+   DESTINATION ${INCLUDE_INSTALL_DIR}/kdeprint2
+)
+
+
+
+
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 716348)
+++ CMakeLists.txt	(working copy)
@@ -180,6 +180,7 @@ add_subdirectory( mimetypes  )
 add_subdirectory( doc  )
 add_subdirectory( kinit  )
 add_subdirectory( kdeprint  )
+add_subdirectory( kdeprint2  )
 add_subdirectory( threadweaver )
 add_subdirectory( sonnet  )
 add_subdirectory( khtml  )


["signature.asc" (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic