Results 1 to 5 of 5

Thread: Cancelling Long-running Print/Print Preview

  1. #1
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Cancelling Long-running Print/Print Preview

    G'day All,

    I have a potentially long running (10-20 seconds) print job that I'm providing a QProgressDialog for. I'd like to be able to cancel the job cleanly.

    My paintRequested() routine first paginates then renders the pages. During pagination I detect a cancellation request and exit the pagination with a boolean flag, which causes the actual rendering to be skipped. A similar check in the rendering routine aborts the rendering.

    I appreciate that what has already gone to the printer cannot be recalled. It would be nice though to have the QPrintPreviewDialog not open if the process was cancelled.

    I was going to emit a custom signal from paintRequested() connected to a slot in the object that owns the preview dialog; it would destroy the QPrintPreviewDialog object. This seems rather draconian. Is there a more elegant way to do this?

    Cheers,
    Chris W

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Cancelling Long-running Print/Print Preview

    You mean that if you cancel a printing operation, the pages that have already been processed should be printed and the remaining ones should just be skipped? This should work provided you just returned from the painting routine after a page has been sent to printer. Can we see the code?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Cancelling Long-running Print/Print Preview

    That's what I am doing. When Cancel is pressed the remaining pages are skipped and only those already painted are physically printed. There's nothing I can do about that.

    When the same code is used on a print preview the preview dialog displays everything up to last processed page after the paintRequested() handler returns. If Cancel is pressed while the paginate is running the preview display a single blank page (as expected).

    What the user expects is that pressing Cancel will terminate the preview process entirely... not displaying the preview with the half-finished output or a blank page. I cannot see a clean way to do this because the paintRequested() slot cannot return a userAborted value or the like.

    The handler for the QPrintPreviewDialog paintRequested() signal and friends look like:
    Qt Code:
    1. void LogView::paintRequested(QPrinter * printer)
    2. {
    3. Q_ASSERT(printer);
    4. m_printer = printer;
    5.  
    6. // Force some settings on the printer
    7. m_printer->setFullPage(true);
    8. m_printer->setPageMargins(0, 0, 0, 0, QPrinter::Millimeter);
    9. m_printer->setOrientation(QPrinter::Landscape);
    10. m_printer->setPageSize(QPrinter::A4);
    11.  
    12. QPainter painter(printer);
    13. // Ensure the geometry is right for the device
    14. calcGeometry(m_printer);
    15. QList< QList<int> > pages;
    16. if (paginate(&painter, &pages))
    17. printPages(&painter, pages);
    18. }
    To copy to clipboard, switch view to plain text mode 
    and
    Qt Code:
    1. void LogView::printPages(QPainter *painter,
    2. const QList< QList<int> > &pages)
    3. {
    4.  
    5. int firstPage = m_printer->fromPage() - 1;
    6. if (firstPage >= pages.size())
    7. return;
    8. if (firstPage == -1)
    9. firstPage = 0;
    10. int lastPage = m_printer->toPage() - 1;
    11. if (lastPage == -1 || lastPage >= pages.size())
    12. lastPage = pages.size() - 1;
    13. int numPages = lastPage - firstPage + 1;
    14. for (int i = 0; i < m_printer->numCopies(); ++i) {
    15. QProgressDialog progress(this);
    16. progress.setLabelText(tr("Printing %1 pages (Copy %2)").arg(numPages).arg(i+1));
    17. progress.setRange(0, numPages-1);
    18. progress.setModal(true);
    19. for (int j = 0; j < numPages; ++j) {
    20. // Process events for responsivness
    21. progress.setValue(j);
    22. qApp->processEvents();
    23. if (progress.wasCanceled()) {
    24. break;
    25. }
    26. if (i != 0 || j != 0)
    27. m_printer->newPage();
    28. int index;
    29. if (m_printer->pageOrder() == QPrinter::FirstPageFirst) {
    30. index = firstPage + j;
    31. } else {
    32. index = lastPage - j;
    33. }
    34. printPage(painter, pages[index], index + 1);
    35. }
    36. if (progress.wasCanceled())
    37. break;
    38. }
    39. }
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Cancelling Long-running Print/Print Preview

    Why don't you perform calculations first and only then do the painting? This way you should get a all-or-nothing semantics. You can make sure you can't cancel the operation while the actual painting is done (so that it becomes an atomic operation).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: Cancelling Long-running Print/Print Preview

    Thanks for the suggestion.

    The pagination is currently separate from the painting. For a 150 page document (~2500 rows from a DB, ugly rendering contortions) pagination is taking in the order of 2.3 seconds (mid-range machine). I could move this outside the paintRequested() handler and not actually invoke QPrintPreviewDialog::exec() if it is canceled.

    The painting itself takes 10+ seconds. I will look into how much of the formatting/calculation can be done without having access to the actual painter... I can move this into a pre-processing stage with the pagination. Since much of it is wrapping text to fit columns and boxes I need to know the font/painter metrics to do this. I don't get the painter until QPrintPreviewDialog emits paintRequested() after exec() and then I am commited to display of at least one blank page even if I render nothing.

    Edit: On reflection, the pagination requires painter metric also. I can certainly cache the result so it need not be repeated when an actual print is done from the preview dialog.
    Last edited by ChrisW67; 16th June 2009 at 23:16.

Similar Threads

  1. long running paint + menu hole
    By hvw59601 in forum Qt Programming
    Replies: 1
    Last Post: 1st November 2007, 13:04

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.