File indexing completed on 2024-03-24 16:41:44
0001 /************************************************************************************************** 0002 Copyright (C) 2005-2007 by Holger Danielsson (holger.danielsson@versanet.de) 0003 2007-2022 by Michel Ludwig (michel.ludwig@kdemail.net) 0004 **************************************************************************************************/ 0005 0006 /*************************************************************************** 0007 * * 0008 * This program is free software; you can redistribute it and/or modify * 0009 * it under the terms of the GNU General Public License as published by * 0010 * the Free Software Foundation; either version 2 of the License, or * 0011 * (at your option) any later version. * 0012 * * 0013 ***************************************************************************/ 0014 0015 #include "quickpreview.h" 0016 #include "kiletool_enums.h" 0017 #include "kiledocmanager.h" 0018 #include "widgets/logwidget.h" 0019 0020 #include <QDir> 0021 #include <QMap> 0022 #include <QFile> 0023 #include <QFileInfo> 0024 #include <QTextCodec> 0025 #include <QTextStream> 0026 0027 #include <KLocalizedString> 0028 0029 #include <KTextEditor/Document> 0030 #include <KTextEditor/View> 0031 0032 #include "errorhandler.h" 0033 #include "kileconstants.h" 0034 #include "kiledebug.h" 0035 0036 0037 namespace KileTool 0038 { 0039 0040 QuickPreview::QuickPreview(KileInfo *ki) : m_ki(ki), m_running(0), m_tempDir(Q_NULLPTR) 0041 { 0042 m_taskList << i18n("LaTeX ---> DVI (Okular)") 0043 << i18n("LaTeX ---> DVI (Document Viewer)") 0044 << i18n("LaTeX ---> PS (Okular)") 0045 << i18n("LaTeX ---> PS (Document Viewer)") 0046 << i18n("PDFLaTeX ---> PDF (Okular)") 0047 << i18n("PDFLaTeX ---> PDF (Document Viewer)") 0048 << i18n("XeLaTeX ---> PDF (Okular)") 0049 << i18n("XeLaTeX ---> PDF (Document Viewer)") 0050 << i18n("LuaLaTeX ---> PDF (Okular)") 0051 << i18n("LuaLaTeX ---> PDF (Document Viewer)") 0052 ; 0053 } 0054 0055 QuickPreview::~QuickPreview() 0056 { 0057 delete m_tempDir; 0058 } 0059 0060 //////////////////// quick preview //////////////////// 0061 0062 // compile and view current selection (singlemode and mastermode) 0063 0064 void QuickPreview::previewSelection(KTextEditor::View *view, bool previewInWidgetConfig) 0065 { 0066 if (view->selection()) { 0067 int startLine = view->selectionRange().start().line(); 0068 KTextEditor::Document *doc = view->document(); 0069 if ( previewInWidgetConfig && KileConfig::selPreviewInWidget() ) { 0070 m_ki->previewWidget()->showActivePreview(view->selectionText(), m_ki->getName(doc), startLine, KileTool::qpSelection); 0071 } 0072 else { 0073 run(view->selectionText(), m_ki->getName(doc), startLine); 0074 view->removeSelection(); 0075 } 0076 } 0077 else { 0078 showError( i18n("There is no selection to compile.") ); 0079 } 0080 } 0081 0082 // compile and view current environment (singlemode and mastermode) 0083 0084 void QuickPreview::previewEnvironment(KTextEditor::Document *doc) 0085 { 0086 int row, col; 0087 QString envname; 0088 QString text = m_ki->editorExtension()->getEnvironmentText(row, col, envname); 0089 if (!text.isEmpty()) { 0090 if(m_ki->latexCommands()->isMathModeEnv(envname)) { 0091 text = '$' + text + '$'; 0092 } 0093 else if (m_ki->latexCommands()->isDisplaymathModeEnv(envname)) { 0094 text = "\\[" + text + "\\]"; 0095 } 0096 0097 if(KileConfig::envPreviewInWidget()) { 0098 m_ki->previewWidget()->showActivePreview(text, m_ki->getName(doc), row, KileTool::qpEnvironment); 0099 } 0100 else { 0101 run(text, m_ki->getName(doc), row); 0102 } 0103 } 0104 else { 0105 showError(i18n("There is no surrounding environment.")); 0106 } 0107 } 0108 0109 // compile and view current subdocument (only mastermode) 0110 0111 void QuickPreview::previewSubdocument(KTextEditor::Document *doc) 0112 { 0113 // this mode is only useful with a master document 0114 if(!m_ki->docManager()->activeProject() && m_ki->getSinglemode()) { 0115 showError(i18n("This job is only useful with a master document.")); 0116 return; 0117 } 0118 0119 // the current document should not be the master document 0120 QString filename = doc->url().toLocalFile(); 0121 if(filename == m_ki->getCompileName()) { 0122 showError( i18n("This is not a subdocument, but the master document.")); 0123 return; 0124 } 0125 0126 run(doc->text(), m_ki->getName(doc), 0); 0127 } 0128 0129 // compile and view current mathgroup (singlemode and mastermode) 0130 0131 void QuickPreview::previewMathgroup(KTextEditor::Document *doc) 0132 { 0133 uint row,col; 0134 QString text = m_ki->editorExtension()->getMathgroupText(row, col); 0135 if (!text.isEmpty()) { 0136 if(KileConfig::mathgroupPreviewInWidget()) { 0137 m_ki->previewWidget()->showActivePreview(text, m_ki->getName(doc), row, KileTool::qpMathgroup); 0138 } 0139 else { 0140 run(text, m_ki->getName(doc), row); 0141 } 0142 } 0143 else { 0144 showError(i18n("There is no surrounding mathgroup.")); 0145 } 0146 0147 } 0148 0149 //////////////////// run quick preview //////////////////// 0150 0151 void QuickPreview::getTaskList(QStringList &tasklist) 0152 { 0153 tasklist.clear(); 0154 tasklist << "Tool/ViewDVI/Okular=" + m_taskList[0] 0155 << "Tool/ViewDVI/Document Viewer=" + m_taskList[1] 0156 << "Tool/ViewPS/Okular=" + m_taskList[2] 0157 << "Tool/ViewPS/Document Viewer=" + m_taskList[3] 0158 << "Tool/ViewPDF/Okular=" + m_taskList[4] 0159 << "Tool/ViewPDF/Document Viewer=" + m_taskList[5] 0160 << "Tool/ViewPDF/Okular=" + m_taskList[6] 0161 << "Tool/ViewPDF/Document Viewer=" + m_taskList[7] 0162 << "Tool/ViewPDF/Okular=" + m_taskList[8] 0163 << "Tool/ViewPDF/Document Viewer=" + m_taskList[9] 0164 ; 0165 } 0166 0167 bool QuickPreview::isRunning() 0168 { 0169 return (m_running > 0); 0170 } 0171 0172 bool QuickPreview::run(const QString &text,const QString &textfilename,int startrow) 0173 { 0174 // define possible tools 0175 QMap <QString,QString> map; 0176 map[m_taskList[0]] = "PreviewLaTeX,,,ViewDVI,Okular,dvi"; 0177 map[m_taskList[1]] = "PreviewLaTeX,,,ViewDVI,Document Viewer,dvi"; 0178 map[m_taskList[2]] = "PreviewLaTeX,DVItoPS,Default,ViewPS,Okular,ps"; 0179 map[m_taskList[3]] = "PreviewLaTeX,DVItoPS,Default,ViewPS,Document Viewer,ps"; 0180 map[m_taskList[4]] = "PreviewPDFLaTeX,,,ViewPDF,Okular,pdf"; 0181 map[m_taskList[5]] = "PreviewPDFLaTeX,,,ViewPDF,Document Viewer,pdf"; 0182 map[m_taskList[6]] = "PreviewXeLaTeX,,,ViewPDF,Okular,pdf"; 0183 map[m_taskList[7]] = "PreviewXeLaTeX,,,ViewPDF,Document Viewer,pdf"; 0184 map[m_taskList[8]] = "PreviewLuaLaTeX,,,ViewPDF,Okular,pdf"; 0185 map[m_taskList[9]] = "PreviewLuaLaTeX,,,ViewPDF,Document Viewer,pdf"; 0186 0187 QString previewtask = KileConfig::previewTask(); 0188 if(!map.contains(previewtask)) { 0189 showError(i18n("Could not run QuickPreview:\nunknown task '%1'",previewtask)); 0190 return false; 0191 } 0192 0193 return run (text, textfilename, startrow, map[previewtask]); 0194 } 0195 0196 bool QuickPreview::run(const QString &text,const QString &textfilename,int startrow,const QString &spreviewlist) 0197 { 0198 KILE_DEBUG_MAIN << "==QuickPreview::run()==========================" << Qt::endl; 0199 m_ki->errorHandler()->clearMessages(); 0200 if(m_running > 0) { 0201 showError( i18n("There is already a preview running that has to be finished to run this one.") ); 0202 return false; 0203 } 0204 0205 // check if there is something to compile 0206 if(text.isEmpty()) { 0207 showError(i18n("There is nothing to compile and preview.")); 0208 return false; 0209 } 0210 0211 delete m_tempDir; 0212 m_tempDir = new QTemporaryDir(QDir::tempPath() + QLatin1Char('/') + "kile-preview"); 0213 m_tempDir->setAutoRemove(true); 0214 m_tempFile = QFileInfo(m_tempDir->path(), "preview.tex").absoluteFilePath(); 0215 KILE_DEBUG_MAIN << "\tdefine tempfile: " << m_tempFile << Qt::endl; 0216 0217 // create the temporary file with preamble and text 0218 int preamblelines = createTempfile(text); 0219 if(preamblelines == 0) { 0220 return false; 0221 } 0222 0223 QStringList previewlist = spreviewlist.split(',', Qt::KeepEmptyParts); 0224 0225 // create preview tools 0226 KILE_DEBUG_MAIN << "\tcreate latex tool for QuickPreview: " << previewlist[pvLatex] << Qt::endl; 0227 KileTool::PreviewLaTeX *latex = dynamic_cast<KileTool::PreviewLaTeX*>(m_ki->toolManager()->createTool(previewlist[pvLatex], QString(), false)); 0228 if(!latex) { 0229 showError(i18n("Could not run '%1' for QuickPreview.", QString("LaTeX"))); 0230 return false; 0231 } 0232 0233 KileTool::Base *dvips = Q_NULLPTR; 0234 if(!previewlist[1].isEmpty()) { 0235 QString dvipstool = previewlist[pvDvips] + " (" + previewlist[pvDvipsCfg] + ')'; 0236 KILE_DEBUG_MAIN << "\tcreate dvips tool for QuickPreview: " << previewlist[pvDvips] << Qt::endl; 0237 dvips = m_ki->toolManager()->createTool(previewlist[pvDvips], previewlist[pvDvipsCfg]); 0238 if(!dvips) { 0239 showError(i18n("Could not run '%1' for QuickPreview.",dvipstool)); 0240 return false; 0241 } 0242 } 0243 0244 KileTool::Base *viewer = Q_NULLPTR; 0245 if(!previewlist[pvViewer].isEmpty()) { 0246 QString viewertool = previewlist[pvViewer] + " (" + previewlist[pvViewerCfg] + ')'; 0247 KILE_DEBUG_MAIN << "\tcreate viewer for QuickPreview: " << viewertool << Qt::endl; 0248 viewer = m_ki->toolManager()->createTool(previewlist[pvViewer], previewlist[pvViewerCfg], false); 0249 if(!viewer) { 0250 showError(i18n("Could not run '%1' for QuickPreview.",viewertool)); 0251 return false; 0252 } 0253 } 0254 0255 // set value of texinput path (only for QuickPreview tools) 0256 QString texinputpath = KileConfig::teXPaths(); 0257 QString inputdir = QFileInfo(m_ki->getCompileName()).absolutePath(); 0258 if(!texinputpath.isEmpty()) { 0259 inputdir += LIST_SEPARATOR + texinputpath; 0260 } 0261 KileConfig::setPreviewTeXPaths(inputdir); 0262 KILE_DEBUG_MAIN << "\tQuickPreview: inputdir is '" << inputdir << "'" << Qt::endl; 0263 0264 // prepare tools: previewlatex 0265 QString filepath = m_tempFile.left(m_tempFile.length() - 3); 0266 latex->setPreviewInfo(textfilename, startrow, preamblelines + 1); 0267 latex->setSource(m_tempFile); 0268 latex->prepareToRun(); 0269 latex->setQuickie(); 0270 connect(latex, SIGNAL(destroyed()), this, SLOT(toolDestroyed())); 0271 m_ki->toolManager()->run(latex); 0272 0273 m_running++; 0274 0275 // dvips 0276 if(dvips) { 0277 dvips->setSource( filepath + "dvi" ); 0278 dvips->setQuickie(); 0279 connect(dvips, SIGNAL(destroyed()), this, SLOT(toolDestroyed())); 0280 m_ki->toolManager()->run(dvips); 0281 0282 m_running++; 0283 } 0284 0285 // viewer 0286 if(viewer) { 0287 connect(viewer, SIGNAL(destroyed()), this, SLOT(toolDestroyed())); 0288 viewer->setSource( filepath + previewlist[pvExtension] ); 0289 viewer->setQuickie(); 0290 m_ki->toolManager()->run(viewer); 0291 } 0292 0293 return true; 0294 } 0295 0296 void QuickPreview::toolDestroyed() 0297 { 0298 KILE_DEBUG_MAIN << "\tQuickPreview: tool destroyed" << Qt::endl; 0299 if(m_running > 0) { 0300 --m_running; 0301 } 0302 } 0303 0304 QString QuickPreview::getPreviewFile(const QString &extension) 0305 { 0306 if (m_tempFile.length () < 3) { 0307 return QString(); 0308 } 0309 0310 QString filepath = m_tempFile.left(m_tempFile.length () - 3); 0311 return filepath + extension; 0312 } 0313 0314 //////////////////// tempfile //////////////////// 0315 0316 int QuickPreview::createTempfile(const QString &text) 0317 { 0318 // determine main document to read the preamble 0319 QString filename = m_ki->getCompileName(); 0320 if(filename.isEmpty()) { 0321 showError(i18n("Could not determine the main document.")); 0322 return 0; 0323 } 0324 0325 // open to read 0326 QFile fin(filename); 0327 if(!fin.exists() || !fin.open(QIODevice::ReadOnly)) { 0328 showError(i18n("Could not read the preamble.")); 0329 return 0; 0330 } 0331 KILE_DEBUG_MAIN << "\tcreate a temporary file: " << m_tempFile << Qt::endl; 0332 0333 // use a textstream 0334 QTextStream preamble(&fin); 0335 0336 // create the temporary file 0337 QFile tempfile(m_tempFile); 0338 if(!tempfile.open(QIODevice::WriteOnly)) { 0339 showError(i18n("Could not create a temporary file.")); 0340 return 0; 0341 } 0342 QTextStream stream(&tempfile); 0343 0344 // set the encoding according to the original file (tbraun) 0345 if(m_ki->activeTextDocument()) { 0346 QTextCodec *codec = QTextCodec::codecForName(m_ki->activeTextDocument()->encoding().toLatin1()); 0347 if(codec) { 0348 stream.setCodec(codec); 0349 } 0350 } 0351 // write the whole preamble into this temporary file 0352 int preamblelines = 0; 0353 bool begindocumentFound = false; 0354 while(!preamble.atEnd()) { 0355 QString textline = preamble.readLine(); 0356 if (textline.indexOf("\\begin{document}") >= 0) { 0357 begindocumentFound = true; 0358 break; 0359 } 0360 stream << textline << "\n"; 0361 preamblelines++; 0362 } 0363 0364 // look if we found '\begin{document}' to finish the preamble 0365 if (!begindocumentFound) { 0366 tempfile.close(); 0367 showError(i18n("Could not find a '\\begin{document}' command.")); 0368 return 0; 0369 } 0370 0371 // add the text to compile 0372 stream << "\\pagestyle{empty}\n"; 0373 stream << "\\begin{document}\n"; 0374 stream << text; 0375 stream << "\n\\end{document}\n"; 0376 tempfile.close(); 0377 0378 return preamblelines; 0379 } 0380 0381 //////////////////// error messages //////////////////// 0382 0383 void QuickPreview::showError(const QString &text) 0384 { 0385 m_ki->errorHandler()->printMessage(KileTool::Error, text, i18n("QuickPreview")); 0386 } 0387 0388 } 0389