File indexing completed on 2024-04-28 16:26:32

0001 /*****************************************************************************
0002 *   Copyright (C) 2006 by Mathias Soeken (msoeken@informatik.uni-bremen.de)  *
0003 *                        (orginal version of this preview)                   *
0004 *             (C) 2011-2019 by Michel Ludwig (michel.ludwig@kdemail.net)          *
0005 ******************************************************************************/
0006 
0007 // dani/2006:
0008 //  - signal/slot communication
0009 //  - user-defined resolution of the png image
0010 //  - add '%res' to the dictionary of KileTools
0011 //  - install three possible conversion methods: dvipng, dvips/convert for documents
0012 //    with postscript source and convert for source, which needs the pdftex driver
0013 //  - preview configuration dialog
0014 
0015 /***************************************************************************
0016  *                                                                         *
0017  *   This program is free software; you can redistribute it and/or modify  *
0018  *   it under the terms of the GNU General Public License as published by  *
0019  *   the Free Software Foundation; either version 2 of the License, or     *
0020  *   (at your option) any later version.                                   *
0021  *                                                                         *
0022  ***************************************************************************/
0023 
0024 #include "widgets/previewwidget.h"
0025 
0026 #include <QImage>
0027 #include <QLabel>
0028 #include <QPainter>
0029 #include <QPaintEvent>
0030 #include <QPalette>
0031 #include <QScrollArea>
0032 
0033 #include <KLocalizedString>
0034 
0035 #include "editorextension.h"
0036 #include "errorhandler.h"
0037 #include "kileconfig.h"
0038 #include "kileinfo.h"
0039 #include "kileviewmanager.h"
0040 #include "kiletool.h"
0041 #include "kiletool_enums.h"
0042 #include "quickpreview.h"
0043 
0044 namespace KileWidget
0045 {
0046 
0047 // We can't use signals/slots in this class as the moc doesn't parse it.
0048 // Also, we better keep the declaration and implementation separate as
0049 // we might have to move it back at some point.
0050 class ImageDisplayWidget : public QWidget
0051 {
0052 public:
0053     ImageDisplayWidget(QWidget *parent);
0054     virtual ~ImageDisplayWidget();
0055 
0056     void clear();
0057     void setImageFile(const QString& fileName);
0058 
0059 protected:
0060     virtual void paintEvent(QPaintEvent *event) override;
0061 
0062 private:
0063     QImage *m_image;
0064 };
0065 
0066 ImageDisplayWidget::ImageDisplayWidget(QWidget *parent)
0067     : QWidget(parent),
0068       m_image(Q_NULLPTR)
0069 {
0070     setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0071 }
0072 
0073 ImageDisplayWidget::~ImageDisplayWidget()
0074 {
0075     delete m_image;
0076 }
0077 
0078 void ImageDisplayWidget::paintEvent(QPaintEvent * /* event */)
0079 {
0080     QPainter p(this);
0081     // draw the background first
0082     p.fillRect(0, 0, width(), height(), KileConfig::previewPaneBackgroundColor());
0083     // and then the image
0084     if(m_image) {
0085         p.drawImage(3, 3, *m_image);
0086     }
0087 }
0088 
0089 void ImageDisplayWidget::clear()
0090 {
0091     delete m_image;
0092     m_image = Q_NULLPTR;
0093     setMinimumSize(0, 0);
0094     repaint();
0095 }
0096 
0097 void ImageDisplayWidget::setImageFile(const QString& fileName)
0098 {
0099     if(!m_image) {
0100         delete m_image;
0101     }
0102 
0103     m_image = new QImage(fileName);
0104     setMinimumSize(m_image->width() + 6, m_image->height() + 6);
0105     repaint();
0106 }
0107 
0108 PreviewWidget::PreviewWidget(KileInfo *info, QWidget *parent, const char *name)
0109     : QScrollArea(parent), m_info(info), m_running(false)
0110 {
0111     setObjectName(name);
0112     setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
0113     setWidgetResizable(true);
0114 
0115     m_imageDisplayWidget = new ImageDisplayWidget(this);
0116     setWidget(m_imageDisplayWidget);
0117 }
0118 
0119 
0120 PreviewWidget::~PreviewWidget()
0121 {
0122 }
0123 
0124 void PreviewWidget::showActivePreview(const QString &text,const QString &textfilename,int startrow,int previewtype)
0125 {
0126     KILE_DEBUG_MAIN << "==PreviewWidget::showActivePreview()==========================";
0127     m_info->errorHandler()->clearMessages();
0128     if(m_running || m_info->quickPreview()->isRunning()) {
0129         showError( i18n("There is already a preview running that has to be finished to run this one.") );
0130         return;
0131     }
0132 
0133     // determine the type of conversion
0134     int conversiontype;
0135     switch(previewtype) {
0136     case KileTool::qpSelection:
0137         conversiontype = KileConfig::selPreviewTool();
0138         break;
0139     case KileTool::qpEnvironment:
0140         conversiontype = KileConfig::envPreviewTool();
0141         break;
0142     case KileTool::qpMathgroup:
0143         conversiontype = KileConfig::mathgroupPreviewTool();
0144         break;
0145     default: // should not happen
0146         conversiontype = pwDvipng;
0147         break;
0148     }
0149 
0150 
0151     // set parameter for these tools
0152     QString tasklist, tool, toolcfg, extension;
0153     if(conversiontype == pwConvert) {
0154         m_conversionTool = "convert";
0155         tasklist = "PreviewPDFLaTeX,,,,,png";
0156         tool = "Convert";
0157         toolcfg = "pdf2png";
0158         extension = "pdf";
0159     }
0160     else if(conversiontype == pwDvipsConvert) {
0161         m_conversionTool = "dvips/convert";
0162         tasklist = "PreviewLaTeX,DVItoPS,dvi2eps,,,png";
0163         tool = "Convert";
0164         toolcfg = "eps2png";
0165         extension = "eps";
0166     }
0167     else {
0168         m_conversionTool = "dvipng";
0169         tasklist = "PreviewLaTeX,,,,,png";
0170         tool = "DVItoPNG";
0171         toolcfg.clear();
0172         extension = "dvi";
0173     }
0174 
0175     if(!m_info->quickPreview()->run(text, textfilename, startrow, tasklist)) {
0176         return;
0177     }
0178 
0179     KileTool::Base *pngConverter = m_info->toolManager()->createTool(tool, toolcfg);
0180     if(!pngConverter) {
0181         showError(i18n("Could not run '%1' for QuickPreview.", tool));
0182         return;
0183     }
0184     pngConverter->setSource(m_info->quickPreview()->getPreviewFile(extension));
0185 
0186     // First, we have to disconnect the old done() signal, because this is
0187     // passed immediately to the toolmanager, whichs destroys the tool. This
0188     // means, that all connections, which are done later, will never been called.
0189     disconnect(pngConverter, SIGNAL(done(KileTool::Base*,int,bool)), m_info->toolManager(), SLOT(done(KileTool::Base*,int)));
0190 
0191     // Now we make some new connections, which are called in this sequence:
0192     // 1) when the tool is finished, the preview will be shown
0193     // 2) then the done() signal can be passed to the toolmanager,
0194     //    which destroys the tool
0195     connect(pngConverter, SIGNAL(done(KileTool::Base*,int,bool)), this, SLOT(drawImage()));
0196     connect(pngConverter, SIGNAL(done(KileTool::Base*,int,bool)), m_info->toolManager(), SLOT(done(KileTool::Base*,int)));
0197 
0198     // Finally we will send a signal, which will pass the focus from the log window
0199     // to the formula preview (dvipng --> toolmanager --> kile)
0200     //
0201     // Remark:
0202     // It's also possible to use only (!) the destroyed() signal. This must be sent
0203     // to the toolmanager, which passes it over to the kile object. This object can
0204     // call drawImage() and after it, we have to set the focus to the preview widget.
0205     // This can only be done from the kile object, which explains this indirect way.
0206     //
0207     // But i (dani) prefer the chosen way above, because
0208     //  - we can distinguish between drawImage() and focusPreview(), which may be
0209     //    important some time
0210     //  - it is more complicated
0211     connect(pngConverter, SIGNAL(destroyed()), m_info->toolManager(), SIGNAL(previewDone()));
0212     connect(pngConverter, SIGNAL(destroyed()), this, SLOT(toolDestroyed()));
0213 
0214     // Now we are ready to start the process...
0215     m_info->toolManager()->run(pngConverter);
0216     m_running = true;
0217 }
0218 
0219 void PreviewWidget::clear()
0220 {
0221     m_imageDisplayWidget->clear();
0222 }
0223 
0224 void PreviewWidget::drawImage()
0225 {
0226     KILE_DEBUG_MAIN << "\tconversion tool '" << m_conversionTool << "' done, processing file (by dani)";
0227     m_imageDisplayWidget->setImageFile(m_info->quickPreview()->getPreviewFile ("png"));
0228 }
0229 
0230 void PreviewWidget::toolDestroyed()
0231 {
0232     KILE_DEBUG_MAIN << "\tQuickPreview: tool destroyed";
0233     m_running = false;
0234 }
0235 
0236 void PreviewWidget::showError(const QString &text)
0237 {
0238     m_info->errorHandler()->printMessage(KileTool::Error, text, i18n("QuickPreview"));
0239 }
0240 
0241 }
0242