Subversion Repositories Scribus

Rev

Rev 24935 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/


#include <QApplication>
#include <QMap>
#include <QScreen>
#include <QTemporaryFile>

#include "outputpreview_pdf.h"
#include "cmsettings.h"
#include "filewatcher.h"
#include "iconmanager.h"
#include "pageitemiterator.h"
#include "pdflib.h"
#include "pdflib_core.h"
#include "prefsfile.h"
#include "prefsmanager.h"
#include "prefstable.h"
#include "sccolor.h"
#include "sccolorengine.h"
#include "scpaths.h"
#include "scribus.h"
#include "scribuscore.h"
#include "scribusdoc.h"
#include "util.h"
#include "util_ghostscript.h"

#include "ui_outputpreviewbase.h"
#include "ui_outputpreview_pdf.h"

OutputPreview_PDF::OutputPreview_PDF(QWidget* parent, ScribusDoc* doc) :
        OutputPreviewBase(parent, doc),
        m_pdfOptions(doc->pdfOptions()),
        m_prefsManager(PrefsManager::instance())
{
        int inkTableWidth = 0;

        setModal(true);
        setWindowIcon(IconManager::instance().loadIcon("AppIcon.png"));

        QString caption = tr("PDF Output Preview");
        setWindowTitle(caption);

        m_havePngAlpha = ScCore->havePNGAlpha();
        m_haveTiffSep  = ScCore->haveTIFFSep();
        getNumericGSVersion(m_gsVersion);

        m_optionsUi = new Ui::OutputPreview_PDF();
        m_optionsUi->setupUi(m_uiBase->optionWidget);

        if (m_haveTiffSep)
        {
                ColorList usedSpots;
                doc->getUsedColors(usedSpots, true);
                QStringList spots = usedSpots.keys();

                m_inkMax = (spots.count() + 4) * 255;
                m_optionsUi->coverThresholdValue->setMaximum((spots.count() + 4) * 100.0);

                m_optionsUi->inkTable->setColumnCount(2);
                m_optionsUi->inkTable->setRowCount(4 + spots.count());
                m_optionsUi->inkTable->setHorizontalHeaderItem(0, new QTableWidgetItem(IconManager::instance().loadIcon("16/show-object.png"), ""));
                m_optionsUi->inkTable->setHorizontalHeaderItem(1, new QTableWidgetItem( tr("Separation Name")));

                QHeaderView *header = m_optionsUi->inkTable->horizontalHeader();
                header->setStretchLastSection(true);
                header->setSectionsMovable(false);
                header->setSectionResizeMode(QHeaderView::Fixed);

                m_optionsUi->inkTable->setColumnWidth(0, 24);
                m_optionsUi->inkTable->verticalHeader()->hide();
                m_optionsUi->inkTable->setFocusPolicy(Qt::NoFocus);
                m_optionsUi->inkTable->setSizeAdjustPolicy(QTableWidget::AdjustToContentsOnFirstShow);

                m_optionsUi->inkTable->setItem(0, 1, new QTableWidgetItem( tr("Cyan")));
                QCheckBox *cp = new QCheckBox(this);
                cp->setFocusPolicy(Qt::NoFocus);
                cp->setChecked(true);
                connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                m_optionsUi->inkTable->setCellWidget(0, 0, cp);
                m_inkVisibilities.insert("Cyan", cp);

                m_optionsUi->inkTable->setItem(1, 1, new QTableWidgetItem( tr("Magenta")));
                cp = new QCheckBox(this);
                cp->setFocusPolicy(Qt::NoFocus);
                cp->setChecked(true);
                connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                m_optionsUi->inkTable->setCellWidget(1, 0, cp);
                m_inkVisibilities.insert("Magenta", cp);

                m_optionsUi->inkTable->setItem(2, 1, new QTableWidgetItem( tr("Yellow")));
                cp = new QCheckBox(this);
                cp->setFocusPolicy(Qt::NoFocus);
                cp->setChecked(true);
                connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                m_optionsUi->inkTable->setCellWidget(2, 0, cp);
                m_inkVisibilities.insert("Yellow", cp);

                m_optionsUi->inkTable->setItem(3, 1, new QTableWidgetItem( tr("Black")));
                cp = new QCheckBox(this);
                cp->setFocusPolicy(Qt::NoFocus);
                cp->setChecked(true);
                connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                m_optionsUi->inkTable->setCellWidget(3, 0, cp);
                m_inkVisibilities.insert("Black", cp);

                for (int sp = 0; sp < spots.count(); ++sp)
                {
                        const QString& spotName = spots.at(sp);
                        m_optionsUi->inkTable->setItem(sp + 4, 1, new QTableWidgetItem(spotName));
                        cp = new QCheckBox(this);
                        cp->setFocusPolicy(Qt::NoFocus);
                        cp->setChecked(true);
                        connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                        m_optionsUi->inkTable->setCellWidget(sp + 4, 0, cp);
                        m_inkVisibilities.insert(spotName, cp);
                }

                inkTableWidth = m_optionsUi->inkTable->columnWidth(1);

                bool inkCoverageEnabled = (m_optionsUi->enableCMYK->isChecked()) && (m_optionsUi->displayInkCoverage->isChecked());
                m_optionsUi->coverThresholdLabel->setEnabled(inkCoverageEnabled);
                m_optionsUi->coverThresholdValue->setEnabled(inkCoverageEnabled);
                m_optionsUi->coverThresholdValue->setSuffix( tr(" %"));
               
                connect(header, SIGNAL(sectionClicked(int)), this, SLOT(toggleAllFromHeader()));
                connect(m_optionsUi->enableCMYK, SIGNAL(clicked()), this, SLOT(toggleCMYK()));
                connect(m_optionsUi->displayInkCoverage, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
                connect(m_optionsUi->inkTable, SIGNAL(cellDoubleClicked(int,int)), this, SLOT(onInkTableCellDoubleClicked(int)));
        }
        else
        {
                m_optionsUi->enableCMYK->setChecked(false);
                m_optionsUi->enableCMYK->setVisible(false);
                m_optionsUi->inkTable->setVisible(false);
                m_optionsUi->displayInkCoverage->setChecked(false);
                m_optionsUi->displayInkCoverage->setVisible(false);
                m_optionsUi->coverThresholdLabel->setVisible(false);
                m_optionsUi->coverThresholdValue->setVisible(false);
        }

        bool cmykEnabled = m_optionsUi->enableCMYK->isChecked();
        m_optionsUi->inkTable->setEnabled(cmykEnabled);
        m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled);
        bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
        m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && isInkCoverageEnabled);
        m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && isInkCoverageEnabled);

        if (m_optionsUi->inkTable->isVisible())
                m_optionsUi->inkTable->setEnabled(m_optionsUi->enableCMYK->isChecked());

        // Restore display settings from preferences
        m_optionsUi->antiAliasing->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.enableAntiAliasing);
        m_optionsUi->showTransparency->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.showTransparency);
        if (m_optionsUi->inkTable->isVisible() && m_optionsUi->inkTable->isEnabled())
        {
                m_optionsUi->enableCMYK->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.cmykPreviewMode);
                m_inkVisibilities["Cyan"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isCyanVisible);
                m_inkVisibilities["Magenta"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isMagentaVisible);
                m_inkVisibilities["Magenta"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isYellowVisible);
                m_inkVisibilities["Yellow"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isBlackVisible);
        }
        m_optionsUi->displayInkCoverage->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.displayInkCoverage);
        m_optionsUi->coverThresholdValue->setValue(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.inkCoverageThreshold);

        // Generate a template name for temporary files
        QTemporaryFile *tempFile = new QTemporaryFile(ScPaths::tempFileDir() + "/scpreview_XXXXXX.pdf");
        if (tempFile->open())
        {
                QString tempFileBase = tempFile->fileName();
                tempFile->setAutoRemove(false);
                tempFile->close();
                m_tempBaseName = QFileInfo(tempFileBase).completeBaseName();
        }
        if (m_tempBaseName.isEmpty())
                m_tempBaseName = "scpreview";
        delete tempFile;

        setPDFOptionsToUi(m_pdfOptions);
       
        // Display preview
        QPixmap previewPix = createPreview(m_doc->currentPageNumber(), qRound(72 * m_scaleFactor));
        m_previewLabel->setPixmap(previewPix);
        m_previewLabel->resize(previewPix.size());

        m_uiBase->pageSelector->setGUIForPage(m_doc->currentPage()->pageNr());

        int w = m_previewLabel->width() + inkTableWidth + 50;
        resize(qMin(ScCore->primaryMainWindow()->screen()->size().width() - 30, w), 500);

        //signals and slots
        connect(m_uiBase->pageSelector, SIGNAL(pageChanged(int)), this, SLOT(jumpToPage(int)));
        connect(m_uiBase->closeButton, SIGNAL(clicked()), this, SLOT(close()));
        connect(m_uiBase->exportButton, SIGNAL(clicked()), this, SIGNAL(doExport()));
        connect(m_uiBase->scaleBox, SIGNAL(activated(int)), this, SLOT(onScaleBoxValueChanged(int)));

        connect(m_optionsUi->pdfVersionCombo, SIGNAL(activated(int)), this, SLOT(onPdfVersionChanged(int)));
        connect(m_optionsUi->outputModeCombo, SIGNAL(activated(int)), this, SLOT(onPdfOutputModeChanged(int)));
        connect(m_optionsUi->mirrorH, SIGNAL(clicked()), this, SLOT(redisplay()));
        connect(m_optionsUi->mirrorV, SIGNAL(clicked()), this, SLOT(redisplay()));
        connect(m_optionsUi->clipToMargins, SIGNAL(clicked()), this, SLOT(redisplay()));
        connect(m_optionsUi->convertSpots, SIGNAL(clicked()), this, SLOT(redisplay()));

        connect(m_optionsUi->antiAliasing, SIGNAL(clicked()), this, SLOT(redisplay()));
        connect(m_optionsUi->showTransparency, SIGNAL(clicked()), this, SLOT(redisplay()));

        connect(m_optionsUi->coverThresholdValue, SIGNAL(valueChanged(double)), this, SLOT(toggleCMYK_Colour()));
}

OutputPreview_PDF::~OutputPreview_PDF()
{
        cleanupTemporaryFiles();
        delete m_optionsUi;
}

bool OutputPreview_PDF::isCMYKPreviewEnabled() const
{
        return m_optionsUi->enableCMYK->isChecked();
}

bool OutputPreview_PDF::isAntialiasingEnabled() const
{
        return m_optionsUi->antiAliasing->isChecked();
}

bool OutputPreview_PDF::isTransparencyEnabled() const
{
        return m_optionsUi->showTransparency->isChecked();
}

bool OutputPreview_PDF::isInkChannelVisible(const QString& ink)
{
        if (m_inkVisibilities.contains(ink))
                return m_inkVisibilities[ink]->isChecked();
        return false;
}

bool OutputPreview_PDF::isInkCoverageEnabled() const
{
        return m_optionsUi->displayInkCoverage->isChecked();
}

double OutputPreview_PDF::inkCoverageThreshold() const
{
        return m_optionsUi->coverThresholdValue->value();
}

void OutputPreview_PDF::cleanupTemporaryFiles()
{
        QString tempFileDir = ScPaths::tempFileDir();
        QFile::remove(tempFileDir + "/" + m_tempBaseName + ".pdf");
        QFile::remove(tempFileDir + "/" + m_tempBaseName + ".png");
        QDir d(tempFileDir + "/", m_tempBaseName + "*", QDir::Name, QDir::Files | QDir::NoSymLinks);
        if ((d.exists()) && (d.count() != 0))
        {
                for (uint i = 0; i < d.count(); i++)
                        QFile::remove(tempFileDir + "/" + d[i]);
        }
}

QPixmap OutputPreview_PDF::createPreview(int pageIndex, int res)
{
        int ret = -1;
        int gsRes = qRound(res * devicePixelRatioF());
        int w = qRound(m_doc->Pages->at(pageIndex)->width() * gsRes / 72.0);
        int h = qRound(m_doc->Pages->at(pageIndex)->height() * gsRes / 72.0);

        qApp->setOverrideCursor(QCursor(Qt::WaitCursor));

        QPixmap pixmap;
        if (pdfOptionsHaveChanged(pageIndex))
        {
                bool success = createPreviewFile(pageIndex);
                if (!success)
                {
                        imageLoadError(pixmap);
                        return pixmap;
                }
        }

        if (optionsHaveChanged(pageIndex))
        {
                if (m_optionsUi->enableCMYK->isChecked() && m_haveTiffSep)
                        ret = renderPreviewSep(pageIndex, gsRes);
                else
                        ret = renderPreview(pageIndex, gsRes);
                if (ret > 0)
                {
                        imageLoadError(pixmap);
                        return pixmap;
                }
        }

        QImage image;
        if (m_optionsUi->enableCMYK->isChecked() && m_haveTiffSep)
        {
                bool loadError;
                int cyan, magenta, yellow, black;

                ScImage im;
                bool mode;
                int w2 = w;
                int h2 = h;
                image = QImage(w2, h2, QImage::Format_ARGB32);
                image.fill(qRgba(0, 0, 0, 0));
               
                QStringList separationNames { "Cyan", "Magenta", "Yellow" };
                CMSettings cms(m_doc, "", Intent_Perceptual);
                cms.allowColorManagement(false);
                for (int i = 0; i < separationNames.count(); ++i)
                {
                        QString separationName = separationNames.at(i);
                        if (!m_inkVisibilities[separationName]->isChecked())
                                continue;
                        if (m_gsVersion < 854)
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif." + separationName + ".tif", 1, cms, ScImage::RGBData, 72, &mode);
                        else if (m_gsVersion <= 905)
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "." + separationName + ".tif", 1, cms, ScImage::RGBData, 72, &mode);
                        else
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(" + separationName + ").tif", 1, cms, ScImage::RGBData, 72, &mode);
                        if (!loadError)
                        {
                                imageLoadError(pixmap);
                                return pixmap;
                        }
                        if (m_optionsUi->displayInkCoverage->isChecked())
                                blendImagesSumUp(image, im);
                        else
                        {
                                int c = (i == 0) ? 255 : 0;
                                int m = (i == 1) ? 255 : 0;
                                int j = (i == 2) ? 255 : 0;
                                blendImages(image, im, ScColor(c, m, j, 0));
                        }
                }

                for (auto sepit = m_sepsToFileNum.begin(); sepit != m_sepsToFileNum.end(); ++sepit)
                {
                        const QCheckBox* checkBox = m_inkVisibilities.value(sepit.key(), nullptr);
                        if (!checkBox || !checkBox->isChecked())
                                continue;
                        QString sepFileName;
                        if (m_gsVersion < 854)
                                sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.s%1.tif").arg(sepit.value());
                        else if (m_gsVersion <= 905)
                                sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".s%1.tif").arg(sepit.value());
                        else
                                sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(%1).tif").arg(sepit.key());
                        if (!im.loadPicture(sepFileName, 1, cms, ScImage::RGBData, 72, &mode))
                        {
                                imageLoadError(pixmap);
                                return pixmap;
                        }
                        if (m_optionsUi->displayInkCoverage->isChecked())
                                blendImagesSumUp(image, im);
                        else
                                blendImages(image, im, m_doc->PageColors[sepit.key()]);
                }
               
                if (m_inkVisibilities["Black"]->isChecked())
                {
                        CMSettings cms(m_doc, "", Intent_Perceptual);
                        cms.allowColorManagement(false);
                        if (m_gsVersion < 854)
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.Black.tif", 1, cms, ScImage::RGBData, 72, &mode);
                        else if (m_gsVersion <= 905)
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".Black.tif", 1, cms, ScImage::RGBData, 72, &mode);
                        else
                                loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(Black).tif", 1, cms, ScImage::RGBData, 72, &mode);
                        if (!loadError)
                        {
                                imageLoadError(pixmap);
                                return pixmap;
                        }
                        if (m_optionsUi->displayInkCoverage->isChecked())
                                blendImagesSumUp(image, im);
                        else
                                blendImages(image, im, ScColor(0, 0, 0, 255));
                }

                if (m_optionsUi->displayInkCoverage->isChecked())
                {
                        uint limitVal = (m_optionsUi->coverThresholdValue->value() * 255) / 100;
                        for (int yi = 0; yi < h2; ++yi)
                        {
                                QRgb *q = (QRgb*) image.scanLine(yi);
                                for (int xi = 0; xi < w2; ++xi)
                                {
                                        uint greyVal = *q;
                                        if (greyVal != 0)
                                        {
                                                if (limitVal == 0)
                                                {
                                                        QColor tmpC;
                                                        tmpC.setHsv((greyVal * 359) / m_inkMax, 255, 255);
                                                        *q = tmpC.rgba();
                                                }
                                                else
                                                {
                                                        int col = qMin(255 - static_cast<int>(((greyVal * 128) / m_inkMax) * 2), 255);
                                                        if ((*q > 0) && (*q < limitVal))
                                                                *q = qRgba(col, col, col, 255);
                                                        else
                                                                *q = qRgba(col, 0, 0, 255);
                                                }
                                        }
                                        else
                                        {
                                                if (!m_optionsUi->showTransparency->isChecked())
                                                        *q = qRgba(255, 255, 255, 255);
                                        }
                                        q++;
                                }
                        }
                }
                else if (m_doc->HasCMS || ScCore->haveCMS())
                {
                        QRgb alphaFF = qRgba(0,0,0,255);
                        QRgb alphaOO = qRgba(255,255,255,0);
                        ScColorMgmtEngine engine = m_doc->colorEngine;
                        ScColorProfile cmykProfile = m_doc->HasCMS ? m_doc->DocPrinterProf : ScCore->defaultCMYKProfile;
                        ScColorProfile rgbProfile  = m_doc->HasCMS ? m_doc->DocDisplayProf : ScCore->defaultRGBProfile;
                        ScColorTransform transCMYK = engine.createTransform(cmykProfile, Format_YMCK_8, rgbProfile, Format_BGRA_8, Intent_Relative_Colorimetric, 0);
                        for (int yi = 0; yi < h2; ++yi)
                        {
                                uchar* ptr = image.scanLine( yi );
                                transCMYK.apply(ptr, ptr, image.width());
                                QRgb *q = (QRgb *) ptr;
                                for (int xi = 0; xi < image.width(); xi++, q++)
                                {
                                        if (m_optionsUi->showTransparency->isChecked())
                                        {
                                                cyan = qRed(*q);
                                                magenta = qGreen(*q);
                                                yellow = qBlue(*q);
                                                if      ((cyan == 255) && (magenta == 255) && (yellow == 255))
                                                        *q = alphaOO;
                                                else
                                                        *q |= alphaFF;
                                        }
                                        else
                                                *q |= alphaFF;
                                }
                        }
                }
                else
                {
                        for (int yi = 0; yi < h2; ++yi)
                        {
                                QRgb *q = (QRgb*) image.scanLine(yi);
                                for (int xi = 0; xi < w2; ++xi)
                                {
                                        cyan = qRed(*q);
                                        magenta = qGreen(*q);
                                        yellow = qBlue(*q);
                                        black = qAlpha(*q);
                                        if ((cyan != 0) || (magenta != 0) || (yellow != 0 ) || (black != 0))
                                                *q = qRgba(255 - qMin(255, cyan + black), 255 - qMin(255, magenta + black), 255 - qMin(255, yellow + black), 255);
                                        else
                                        {
                                                if (!m_optionsUi->showTransparency->isChecked())
                                                        *q = qRgba(255, 255, 255, 255);
                                        }
                                        q++;
                                }
                        }
                }
        }
        else
        {
                QString previewFile;
                if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
                        previewFile = ScPaths::tempFileDir() + "/" + m_tempBaseName + ".png";
                else
                        previewFile = ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif";
                if (!image.load(previewFile))
                {
                        imageLoadError(pixmap);
                        return pixmap;
                }
                image = image.convertToFormat(QImage::Format_ARGB32);
                if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
                {
                        int wi = image.width();
                        int hi = image.height();
                        for (int yi = 0; yi < hi; ++yi)
                        {
                                QRgb *s = (QRgb*) image.scanLine(yi);
                                for (int xi = 0; xi < wi; ++xi)
                                {
                                        if ((*s) == 0xffffffff)
                                                (*s) &= 0x00ffffff;
                                        s++;
                                }
                        }
                }
        }

        image.setDevicePixelRatio(devicePixelRatioF());
        if (m_optionsUi->showTransparency->isChecked())
        {
                pixmap = QPixmap(image.width(), image.height());
                pixmap.setDevicePixelRatio(devicePixelRatioF());
                QPainter p;
                QBrush b(QColor(205,205,205), IconManager::instance().loadPixmap("testfill.png"));
                p.begin(&pixmap);
                p.fillRect(0, 0, image.width(), image.height(), b);
                p.drawImage(0, 0, image);
                p.end();
        }
        else
                pixmap = QPixmap::fromImage(image);
        pixmap.setDevicePixelRatio(devicePixelRatioF());

        qApp->restoreOverrideCursor();
        updateOptionsFromUI();
        return pixmap;
}

bool OutputPreview_PDF::createPreviewFile(int pageIndex)
{
        if (!m_fontEmbeddingWasSet)
        {
                setupFontEmbedding(m_pdfOptions);
                m_fontEmbeddingWasSet = true;
        }

        std::vector<int> pageNumbers { pageIndex + 1 };

        setUiOptionsToPDFOptions(m_pdfOptions);
        m_pdfOptions.Encrypt = false; // Disable PDF encryption for preview
        m_pdfOptions.Thumbnails = false; //Disable thumbnails too

        QString profileDescription;
        if ((m_pdfOptions.Version == PDFVersion::PDF_X3) || (m_pdfOptions.Version == PDFVersion::PDF_X1a) || (m_pdfOptions.Version == PDFVersion::PDF_X4))
        {
                if (m_pdfOptions.Info.isEmpty())
                {
                        auto& printerProfiles = ScCore->PrinterProfiles;
                        ScColorProfile outputProfile = m_doc->colorEngine.openProfileFromFile( printerProfiles[m_pdfOptions.PrintProf] );
                        profileDescription = outputProfile.productDescription();
                        m_pdfOptions.Info = profileDescription;
                }
                m_pdfOptions.MirrorH = false;
                m_pdfOptions.MirrorV = false;
                m_pdfOptions.PresentMode = false;
        }

        // Disable crop marks
        m_pdfOptions.cropMarks = false;
        m_pdfOptions.bleedMarks = false;
        m_pdfOptions.registrationMarks = false;
        m_pdfOptions.colorMarks = false;
        m_pdfOptions.markLength = 20.0;
        m_pdfOptions.markOffset = 0.0;
        m_pdfOptions.bleeds.set(0, 0, 0, 0);

        // Generate PDF
//      QString errorString;
        QString pdfFileName = ScPaths::tempFileDir() + "/"  + m_tempBaseName + ".pdf";
       
        ScCore->fileWatcher->forceScan();
        ScCore->fileWatcher->stop();
        PDFlib pdflib(*m_doc, m_pdfOptions);
        bool success = pdflib.doExport(pdfFileName, pageNumbers, QMap<int, QImage>());
        success &= !pdflib.exportAborted();
        ScCore->fileWatcher->start();

        return success;
}

int OutputPreview_PDF::renderPreview(int pageIndex, int res)
{
        int ret = -1;
        QString cmd1;

        QStringList args;
        QString tmp, tmp2, tmp3;
        int w = qRound(m_doc->Pages->at(pageIndex)->width() * res / 72.0);
        int h = qRound(m_doc->Pages->at(pageIndex)->height() * res / 72.0);
       
        args.append( "-q" );
        args.append( "-dNOPAUSE" );
        args.append( "-dPARANOIDSAFER" );
        args.append( QString("-r%1").arg(tmp.setNum(res)) );
        args.append( QString("-g%1x%2").arg(tmp2.setNum(w), tmp3.setNum(h)) );
        if (m_optionsUi->enableCMYK->isChecked())
        {
                if (!m_haveTiffSep)
                        return 1;
                args.append("-sDEVICE=tiffsep");
        }
        else
        {
                if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
                        args.append("-sDEVICE=pngalpha");
                else
                        args.append("-sDEVICE=tiff24nc");      
        }
        if (m_optionsUi->antiAliasing->isChecked())
        {
                args.append("-dTextAlphaBits=4");
                args.append("-dGraphicsAlphaBits=4");
        }
        if ((m_doc->HasCMS) && (m_gsVersion >= 900))
        {
                args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
                if (m_optionsUi->enableCMYK->isChecked())
                        args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
                else
                        args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocDisplayProf.profilePath()));
        }
        else if (ScCore->haveCMS() && (m_gsVersion >= 900))
        {
                args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
                if (m_optionsUi->enableCMYK->isChecked())
                        args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
                else
                        args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultRGBProfile.profilePath()));
        }

        // Add any extra font paths being used by Scribus to gs's font search path
        PrefsContext *pc = m_prefsManager.prefsFile->getContext("Fonts");
        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
        const char sep = ScPaths::envPathSeparator;
        if (extraFonts->getRowCount() >= 1)
                cmd1 = QString("-sFONTPATH=%1").arg(QDir::toNativeSeparators(extraFonts->get(0,0)));
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
                cmd1 += QString("%1%2").arg(sep).arg(QDir::toNativeSeparators(extraFonts->get(i,0)));
        if (!cmd1.isEmpty())
                args.append( cmd1 );

        // then add any final args and call gs
        QString tempFileDir = ScPaths::tempFileDir() ;
        if (m_optionsUi->enableCMYK->isChecked())
                args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".tif")) );
        else if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
                args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".png")) );
        else
                args.append(QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".tif")));
        args.append( QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".pdf") );
        args.append( "-c" );
        args.append( "showpage" );
        args.append( "-c" );
        args.append( "quit" );
        ret = System(m_prefsManager.ghostscriptExecutable(), args);
        return ret;
}

int OutputPreview_PDF::renderPreviewSep(int pageIndex, int res)
{
        int ret = -1;
        QString cmd;
        QStringList args, args1, args2, args3;

        QString tmp, tmp2, tmp3;
        int w = qRound(m_doc->Pages->at(pageIndex)->width() * res / 72.0);
        int h = qRound(m_doc->Pages->at(pageIndex)->height() * res / 72.0);

        args1.append( "-q" );
        args1.append( "-dNOPAUSE" );
        args1.append( "-dPARANOIDSAFER" );
        args1.append( QString("-r%1").arg(tmp.setNum(res)) );
        args1.append( QString("-g%1x%2").arg(tmp2.setNum(w), tmp3.setNum(h)) );
        if (m_optionsUi->antiAliasing->isChecked())
        {
                args1.append("-dTextAlphaBits=4");
                args1.append("-dGraphicsAlphaBits=4");
        }
        if ((m_doc->HasCMS) && (m_gsVersion >= 900))
        {
                args1.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
                args1.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
        }
        else if (ScCore->haveCMS() && (m_gsVersion >= 900))
        {
                args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
                args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
        }

        // Add any extra font paths being used by Scribus to gs's font search path
        PrefsContext *pc = m_prefsManager.prefsFile->getContext("Fonts");
        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
        const char sep = ScPaths::envPathSeparator;
        if (extraFonts->getRowCount() >= 1)
                cmd = QString("-sFONTPATH=%1").arg(QDir::toNativeSeparators(extraFonts->get(0,0)));
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
                cmd += QString("%1%2").arg(sep).arg(QDir::toNativeSeparators(extraFonts->get(i,0)));
        if (!cmd.isEmpty())
                args1.append(cmd);
        args1.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif")) );

        args2.append( QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".pdf") );
        args2.append("-c");
        args2.append("quit");

        ColorList usedSpots;
        m_doc->getUsedColors(usedSpots, true);
        QStringList spots = usedSpots.keys();
        args3.append( "-sDEVICE=tiffsep" );

//      args3.append( "-c" );
        cmd = "<< /SeparationColorNames ";
        QString allSeps ="[ /Cyan /Magenta /Yellow /Black ";
        for (int sp = 0; sp < spots.count(); ++sp)
        {
                allSeps += "(" + spots[sp] + ") ";
        }
        allSeps += "]";
        cmd += allSeps + " /SeparationOrder [ /Cyan /Magenta /Yellow /Black] >> setpagedevice";
        QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".sep.ps"));
        if (fx.open(QIODevice::WriteOnly))
        {
                QTextStream tsx(&fx);
                tsx << cmd;
                fx.close();
        }

        QString gsExe(getShortPathName(m_prefsManager.ghostscriptExecutable()));
        ret = System(gsExe, args1 + args3 + args2, ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".tif.txt" );

        QFile sepInfo(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".tif.txt"));
        m_sepsToFileNum.clear();
        if (sepInfo.open(QIODevice::ReadOnly))
        {
                QString Sname;
                QTextStream tsC(&sepInfo);
                int counter = 0;
                while (!tsC.atEnd())
                {
                        Sname = tsC.readLine();
                        QString tt = Sname.remove("%%SeparationName:").trimmed();
                        if (!tt.isEmpty())
                        {
                                m_sepsToFileNum.insert(tt, counter);
                                counter++;
                        }
                }
        }
        sepInfo.close();
        QString currSeps;
        uint spc = 0;
        for (int sp = 0; sp < spots.count(); ++sp)
        {
                currSeps += "(" + spots[sp] + ") ";
                spc++;
                if (sp > 6)
                {
                        args3.clear();
                        args3.append("-sDEVICE=tiffsep");
                        QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".sep.ps"));
                        if (fx.open(QIODevice::WriteOnly))
                        {
                                QTextStream tsx(&fx);
                                tsx << QString("<< /SeparationColorNames " + allSeps + " /SeparationOrder [ " + currSeps + " ] >> setpagedevice");
                                fx.close();
                        }
                        args3.append("-f");
                        args3.append(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".sep.ps"));
                        ret = System(gsExe, args1 + args3 + args2);
                        currSeps = "";
                        spc = 0;
                }
        }
        if (spc != 0)
        {
                args3.clear();
                args3.append("-sDEVICE=tiffsep");
                QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".sep.ps"));
                if (fx.open(QIODevice::WriteOnly))
                {
                        QTextStream tsx(&fx);
                        tsx << QString("<< /SeparationColorNames " + allSeps + " /SeparationOrder [ " + currSeps + " ] >> setpagedevice");
                        fx.close();
                }
                args3.append("-f");
                args3.append(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" +  m_tempBaseName + ".sep.ps"));
                ret = System(gsExe, args1 + args3 + args2);
        }
        return ret;
}

void OutputPreview_PDF::setupFontEmbedding(PDFOptions& options)
{
        QMap<QString, int> usedFonts = m_doc->reorganiseFonts();
        QStringList docFonts = usedFonts.keys();

        // Simple case: no font embedding
        if (m_pdfOptions.FontEmbedding == PDFOptions::DontEmbed)
        {
                m_pdfOptions.OutlineList.clear();
                m_pdfOptions.EmbedList.clear();
                m_pdfOptions.SubsetList.clear();
                return;
        }

        // Simple case: all fonts are outlined
        if (m_pdfOptions.FontEmbedding == PDFOptions::OutlineFonts)
        {
                m_pdfOptions.OutlineList = docFonts;
                m_pdfOptions.EmbedList.clear();
                m_pdfOptions.SubsetList.clear();
                return;
        }

        if (m_pdfOptions.EmbedList.count() != 0)
        {
                QList<QString> tmpEm;
                for (auto itef = m_pdfOptions.EmbedList.begin(); itef != m_pdfOptions.EmbedList.end(); ++itef)
                {
                        if (usedFonts.contains((*itef)))
                                tmpEm.append((*itef));
                }
                m_pdfOptions.EmbedList = tmpEm;
        }
        if (m_pdfOptions.SubsetList.count() != 0)
        {
                QList<QString> tmpEm;
                for (auto itef = m_pdfOptions.SubsetList.begin(); itef != m_pdfOptions.SubsetList.end(); ++itef)
                {
                        if (usedFonts.contains((*itef)))
                                tmpEm.append((*itef));
                }
                m_pdfOptions.SubsetList = tmpEm;
        }

        // Build a list of all fonts used in Annotations
        QMap<QString, QString> annotationFonts;

        int pageItOptions = PageItemIterator::IterateInGroups | PageItemIterator::IterateInDocItems | PageItemIterator::IterateInMasterItems | PageItemIterator::IterateInFrameItems;
        for (PageItemIterator it(m_doc, pageItOptions); *it; ++it)
        {
                PageItem *currItem = *it;
                if (((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText)) && (currItem->isAnnotation()))
                {
                        int annotType  = currItem->annotation().Type();
                        bool mustEmbed = ((annotType >= Annotation::Button) && (annotType <= Annotation::Listbox) && (annotType != Annotation::Checkbox));
                        if (currItem->itemText.length() > 0 || mustEmbed)
                                annotationFonts.insert(currItem->itemText.defaultStyle().charStyle().font().replacementName(), QString());
                }
        }

        const auto& allFonts = m_prefsManager.appPrefs.fontPrefs.AvailFonts;
        PDFVersion pdfVer = m_pdfOptions.Version;

        if ((m_pdfOptions.EmbedList.count() == 0) && (m_pdfOptions.SubsetList.count() == 0) && (m_pdfOptions.firstUse))
        {
                for (int i = 0; i < docFonts.count(); ++i)
                {
                        QString fontName = docFonts.at(i);
                        const ScFace fontFace = allFonts[fontName];
                        if (!fontFace.subset() && (!fontFace.isOTF() || pdfVer.supportsEmbeddedOpenTypeFonts()))
                                m_pdfOptions.EmbedList.append(fontName);
                        else if (annotationFonts.contains(fontName))
                                m_pdfOptions.EmbedList.append(fontName);
                        else
                                m_pdfOptions.SubsetList.append(fontName);
                }
        }
        else
        {
                for (int i = 0; i < docFonts.count(); ++i)
                {
                        QString fontName = docFonts.at(i);
                        const ScFace fontFace = allFonts[fontName];
                        if (m_pdfOptions.EmbedList.contains(fontName) && (!fontFace.isOTF() || m_pdfOptions.supportsEmbeddedOpenTypeFonts()) && !fontFace.subset())
                                continue;
                        if (!m_pdfOptions.SubsetList.contains(fontName))
                                m_pdfOptions.SubsetList.append(fontName);
                }

                for (auto itAnn = annotationFonts.begin(); itAnn != annotationFonts.end(); ++itAnn)
                {
                        const QString& annotFont = itAnn.key();
                        if (!m_pdfOptions.EmbedList.contains(annotFont))
                                m_pdfOptions.EmbedList.append(annotFont);
                        int subsetIndex = m_pdfOptions.SubsetList.indexOf(annotFont);
                        if (subsetIndex >= 0)
                                m_pdfOptions.SubsetList.removeAll(annotFont);
                }
        }
}

bool OutputPreview_PDF::optionsHaveChanged(int pageIndex) const
{
        if (m_currentPage != pageIndex)
                return true;
        if (m_scaleMode != m_uiBase->scaleBox->currentIndex())
                return true;
        if (m_cmykPreviewMode != m_optionsUi->enableCMYK->isChecked())
                return true;
        if (m_useAntialiasing != m_optionsUi->antiAliasing->isChecked())
                return true;
        if (m_showTransparency != m_optionsUi->showTransparency->isChecked())
                return true;

        if (m_pdfVersion != m_optionsUi->pdfVersionCombo->version())
                return true;
        if (m_pdfOutputMode != m_optionsUi->outputModeCombo->currentIndex())
                return true;
        if (m_mirrorH != m_optionsUi->mirrorH->isChecked())
                return true;
        if (m_mirrorV != m_optionsUi->mirrorV->isChecked())
                return true;
        if (m_clipToMargins != m_optionsUi->clipToMargins->isChecked())
                return true;
        if (m_convertSpots != m_optionsUi->convertSpots->isChecked())
                return true;

        return false;
}

bool OutputPreview_PDF::pdfOptionsHaveChanged(int pageIndex) const
{
        if (m_currentPage != pageIndex)
                return true;

        if (m_pdfVersion != m_optionsUi->pdfVersionCombo->version())
                return true;
        if (m_pdfOutputMode != m_optionsUi->outputModeCombo->currentIndex())
                return true;
        if (m_mirrorH != m_optionsUi->mirrorH->isChecked())
                return true;
        if (m_mirrorV != m_optionsUi->mirrorV->isChecked())
                return true;
        if (m_clipToMargins != m_optionsUi->clipToMargins->isChecked())
                return true;
        if (m_convertSpots != m_optionsUi->convertSpots->isChecked())
                return true;

        return false;
}

void OutputPreview_PDF::setPDFOptionsToOptions(PDFOptions& pdfOptions)
{
        m_pdfVersion = pdfOptions.Version;

        if (pdfOptions.UseRGB)
                m_pdfOutputMode = 0;
        else if (pdfOptions.isGrayscale)
                m_pdfOutputMode = 2;
        else
                m_pdfOutputMode = 1;

        m_mirrorH = pdfOptions.MirrorH;
        m_mirrorV = pdfOptions.MirrorV;
        m_clipToMargins = pdfOptions.doClip;
        m_convertSpots  = !pdfOptions.UseSpotColors;
}

void OutputPreview_PDF::setPDFOptionsToUi(PDFOptions& pdfOptions)
{
        m_optionsUi->pdfVersionCombo->setPDFXEnabled(m_doc->HasCMS && !ScCore->PDFXProfiles.isEmpty());
        m_optionsUi->pdfVersionCombo->setVersion(pdfOptions.Version);

        if (pdfOptions.UseRGB)
                m_optionsUi->outputModeCombo->setCurrentIndex(0);
        else if (pdfOptions.isGrayscale)
                m_optionsUi->outputModeCombo->setCurrentIndex(2);
        else
                m_optionsUi->outputModeCombo->setCurrentIndex(1);

        m_optionsUi->mirrorH->setChecked(pdfOptions.MirrorH);
        m_optionsUi->mirrorV->setChecked(pdfOptions.MirrorV);
        m_optionsUi->clipToMargins->setChecked(pdfOptions.doClip);
        m_optionsUi->convertSpots->setChecked(!pdfOptions.UseSpotColors);

        bool cmykEnabled = (m_optionsUi->outputModeCombo->currentIndex() > 0);
        bool cmykUserEnabled = m_optionsUi->enableCMYK->isChecked();

        m_optionsUi->enableCMYK->setEnabled(cmykEnabled);
        m_optionsUi->enableCMYK->setChecked(cmykEnabled && cmykUserEnabled);
        m_optionsUi->inkTable->setEnabled(cmykEnabled && cmykUserEnabled);
        m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled && cmykUserEnabled);
        bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
        m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
        m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
}

void OutputPreview_PDF::setUiOptionsToPDFOptions(PDFOptions& pdfOptions)
{
        pdfOptions.Version = m_optionsUi->pdfVersionCombo->version();
        if (!pdfOptions.Version.supportsOCGs())
                pdfOptions.useLayers = false;

        if (m_optionsUi->outputModeCombo->currentIndex() == 0)
        {
                pdfOptions.isGrayscale = false;
                pdfOptions.UseRGB = true;
                pdfOptions.UseProfiles = false;
                pdfOptions.UseProfiles2 = false;
        }
        else if (m_optionsUi->outputModeCombo->currentIndex() == 2)
        {
                pdfOptions.isGrayscale = true;
                pdfOptions.UseRGB = false;
                pdfOptions.UseProfiles = false;
                pdfOptions.UseProfiles2 = false;
        }
        else
        {
                pdfOptions.isGrayscale = false;
                pdfOptions.UseRGB = false;
                /*if (ScCore->haveCMS())
                {
                        pdfOptions.UseProfiles = EmbedProfs->isChecked();
                        pdfOptions.UseProfiles2 = EmbedProfs2->isChecked();
                        pdfOptions.Intent = IntendS->currentIndex();
                        pdfOptions.Intent2 = IntendI->currentIndex();
                        pdfOptions.EmbeddedI = NoEmbedded->isChecked();
                        pdfOptions.SolidProf = SolidPr->currentText();
                        pdfOptions.ImageProf = ImageP->currentText();
                        pdfOptions.PrintProf = PrintProfC->currentText();
                }*/

        }
       
        // Force font embedding for PDF-X/1
        if (pdfOptions.Version.isPDFX() && (pdfOptions.FontEmbedding == PDFOptions::DontEmbed))
        {
                m_fontEmbeddingWasSet = false;
                pdfOptions.EmbedList.clear();
                pdfOptions.SubsetList.clear();
                pdfOptions.FontEmbedding = PDFOptions::EmbedFonts;
                setupFontEmbedding(m_pdfOptions);
                m_fontEmbeddingWasSet = true;
        }
       
        // PDF/X-1, no profile embedding
        if (pdfOptions.Version == PDFVersion::PDF_X1a)
        {
                pdfOptions.UseProfiles = false;
                pdfOptions.UseProfiles2 = false;
        }
        // PDF/X-3 or PDF/X-4, enforcing color profiles on images
        if (pdfOptions.Version == PDFVersion::PDF_X3 || pdfOptions.Version == PDFVersion::PDF_X4)
                pdfOptions.UseProfiles2 = true;

        pdfOptions.MirrorH = m_optionsUi->mirrorH->isChecked();
        pdfOptions.MirrorV = m_optionsUi->mirrorV->isChecked();
        pdfOptions.doClip  = m_optionsUi->clipToMargins->isChecked();
        pdfOptions.UseSpotColors = !m_optionsUi->convertSpots->isChecked();
}

void OutputPreview_PDF::updateOptionsFromUI()
{
        m_pdfVersion = m_optionsUi->pdfVersionCombo->version();
        m_pdfOutputMode = m_optionsUi->outputModeCombo->currentIndex();
        m_mirrorH = m_optionsUi->mirrorH->isChecked();
        m_mirrorV = m_optionsUi->mirrorV->isChecked();
        m_clipToMargins = m_optionsUi->clipToMargins->isChecked();
        m_convertSpots = m_optionsUi->convertSpots->isChecked();

        m_currentPage = m_uiBase->pageSelector->getCurrentPage() - 1;
        m_scaleMode = m_uiBase->scaleBox->currentIndex();
        m_cmykPreviewMode = m_optionsUi->enableCMYK->isChecked();
        m_useAntialiasing = m_optionsUi->antiAliasing->isChecked();
        m_showTransparency = m_optionsUi->showTransparency->isChecked();
}

void OutputPreview_PDF::onPdfVersionChanged(int index)
{
        bool isPDFX = m_optionsUi->pdfVersionCombo->versionIsPDFX();
        m_optionsUi->outputModeCombo->setEnabled(!isPDFX);

        if (isPDFX)
        {
                m_optionsUi->outputModeCombo->setCurrentIndex(1);
                m_optionsUi->outputModeCombo->setEnabled(false);
                onPdfOutputModeChanged(1);
        }

        redisplay();
}

void OutputPreview_PDF::onPdfOutputModeChanged(int /*index*/)
{
        bool cmykEnabled = (m_optionsUi->outputModeCombo->currentIndex() > 0);
        bool cmykUserEnabled = m_optionsUi->enableCMYK->isChecked();

        m_optionsUi->enableCMYK->setEnabled(cmykEnabled);
        m_optionsUi->enableCMYK->setChecked(cmykEnabled && cmykUserEnabled);
        m_optionsUi->inkTable->setEnabled(cmykEnabled && cmykUserEnabled);
        m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled && cmykUserEnabled);
        bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
        m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
        m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);

        redisplay();
}

void OutputPreview_PDF::onInkTableCellDoubleClicked(int row)
{
        if (!m_haveTiffSep)
                return;

        for (auto sepIt = m_inkVisibilities.begin(); sepIt != m_inkVisibilities.end(); ++sepIt)
                sepIt.value()->setChecked(false);
        ((QCheckBox*)(m_optionsUi->inkTable->cellWidget(row, 0)))->setChecked(true);

        if (m_optionsUi->enableCMYK->isChecked())
                m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
        m_previewLabel->resize(m_previewLabel->pixmap().size());
}

void OutputPreview_PDF::toggleAllFromHeader()
{
        if (!m_haveTiffSep)
                return;

        for (auto sepIt = m_inkVisibilities.begin(); sepIt != m_inkVisibilities.end(); ++sepIt)
                sepIt.value()->setChecked(true);

        if (m_optionsUi->enableCMYK->isChecked())
                m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
        m_previewLabel->resize(m_previewLabel->pixmap().size());
}

void OutputPreview_PDF::toggleCMYK()
{
        if (!m_haveTiffSep)
                return;

        bool cmykEnabled = m_optionsUi->enableCMYK->isChecked();
        m_optionsUi->inkTable->setEnabled(cmykEnabled);
        m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled);
        bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
        m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && isInkCoverageEnabled);
        m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && isInkCoverageEnabled);

        redisplay();
}

void OutputPreview_PDF::toggleCMYK_Colour()
{
        if (m_haveTiffSep)
        {
                bool inkCoverageEnabled = (m_optionsUi->enableCMYK->isChecked()) && (m_optionsUi->displayInkCoverage->isChecked());
                m_optionsUi->coverThresholdLabel->setEnabled(inkCoverageEnabled);
                m_optionsUi->coverThresholdValue->setEnabled(inkCoverageEnabled);
        }
        if (m_optionsUi->enableCMYK->isChecked())
                m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
        m_previewLabel->resize(m_previewLabel->pixmap().size());
}

void OutputPreview_PDF::imageLoadError(QPixmap &pixmap)
{
        pixmap = QPixmap(1, 1);
        qApp->restoreOverrideCursor();
        updateOptionsFromUI();
}