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