File indexing completed on 2024-04-21 05:03:25
0001 /************************************************************************************** 0002 begin : Thu Nov 27 2003 0003 copyright : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net) 0004 (C) 2011-2017 by Michel Ludwig (michel.ludwig@kdemail.net) 0005 **************************************************************************************/ 0006 0007 /*************************************************************************** 0008 * * 0009 * This program is free software; you can redistribute it and/or modify * 0010 * it under the terms of the GNU General Public License as published by * 0011 * the Free Software Foundation; either version 2 of the License, or * 0012 * (at your option) any later version. * 0013 * * 0014 ***************************************************************************/ 0015 0016 #include "kilestdtools.h" 0017 0018 #include <QFileInfo> 0019 #include <QRegExp> 0020 0021 #include <QAction> 0022 #include <KActionCollection> 0023 #include <KConfig> 0024 #include <KLocalizedString> 0025 0026 #include <KProcess> 0027 0028 #include "dialogs/listselector.h" 0029 #include "kileconfig.h" 0030 #include "kiletool.h" 0031 #include "kiletoolmanager.h" 0032 #include "kiletool_enums.h" 0033 #include "kileinfo.h" 0034 #include "kiledocmanager.h" 0035 #include "documentinfo.h" 0036 #include "outputinfo.h" 0037 #include "parser/parsermanager.h" 0038 #include "utilities.h" 0039 0040 #define SHORTCUTS_GROUP_NAME "Shortcuts" 0041 0042 namespace KileTool 0043 { 0044 Factory::Factory(Manager *mngr, KConfig *config, KActionCollection *actionCollection) 0045 : m_manager(mngr), m_config(config), m_actionCollection(actionCollection) 0046 { 0047 m_standardToolConfigurationFileName = KileUtilities::locate(QStandardPaths::AppDataLocation, "kilestdtools.rc"); 0048 } 0049 0050 Factory::~Factory() 0051 { 0052 } 0053 0054 Base* Factory::create(const QString& toolName, const QString& config, bool prepare /* = true */) 0055 { 0056 KILE_DEBUG_MAIN << toolName << config << prepare; 0057 KileTool::Base *tool = Q_NULLPTR; 0058 //perhaps we can find the tool in the config file 0059 if (m_config->hasGroup(groupFor(toolName, m_config))) { 0060 KConfigGroup configGroup = m_config->group(groupFor(toolName, m_config)); 0061 QString toolClass = configGroup.readEntry("class", QString()); 0062 0063 if(toolClass == "LaTeX") { 0064 tool = new LaTeX(toolName, m_manager, prepare); 0065 } 0066 else if(toolClass == "LaTeXpreview") { 0067 tool = new PreviewLaTeX(toolName, m_manager, prepare); 0068 } 0069 else if(toolClass == "LaTeXLivePreview") { 0070 tool = new LivePreviewLaTeX(toolName, m_manager, prepare); 0071 } 0072 else if(toolClass == "ForwardDVI") { 0073 tool = new ForwardDVI(toolName, m_manager, prepare); 0074 } 0075 else if(toolClass == "ViewHTML") { 0076 tool = new ViewHTML(toolName, m_manager, prepare); 0077 } 0078 else if(toolClass == "ViewBib") { 0079 tool = new ViewBib(toolName, m_manager, prepare); 0080 } 0081 else if(toolClass == "Base") { 0082 tool = new Base(toolName, m_manager, prepare); 0083 } 0084 else if(toolClass == "Compile") { 0085 tool = new Compile(toolName, m_manager, prepare); 0086 } 0087 else if (BibliographyCompile::ToolClass == toolClass) { 0088 tool = new BibliographyCompile(toolName, m_manager, prepare); 0089 } 0090 else if(toolClass == "Convert") { 0091 tool = new Convert(toolName, m_manager, prepare); 0092 } 0093 else if(toolClass == "Archive") { 0094 tool = new Archive(toolName, m_manager, prepare); 0095 } 0096 else if(toolClass == "View") { 0097 tool = new View(toolName, m_manager, prepare); 0098 } 0099 else if(toolClass == "Sequence") { 0100 tool = new Sequence(toolName, m_manager, prepare); 0101 } 0102 } 0103 if(!tool) { 0104 return Q_NULLPTR; 0105 } 0106 0107 if(!m_manager->configure(tool, config)) { 0108 delete tool; 0109 return Q_NULLPTR; 0110 } 0111 tool->setToolConfig(config); 0112 0113 // this has to be done after the configuration step only! 0114 if(dynamic_cast<KileTool::Sequence*>(tool)) { 0115 dynamic_cast<KileTool::Sequence*>(tool)->setupSequenceTools(); 0116 } 0117 0118 return tool; 0119 } 0120 0121 void Factory::resetToolConfigurations() 0122 { 0123 KConfig stdToolConfig(m_standardToolConfigurationFileName, KConfig::NoGlobals); 0124 0125 m_config->deleteGroup(QLatin1String("Tools")); 0126 m_config->deleteGroup(QLatin1String("ToolsGUI")); 0127 0128 // we delete all the groups whose names start with "Tool/"; 0129 for (const QString& groupName : m_config->groupList()) { 0130 if(groupName.startsWith(QLatin1String("Tool/"))) { 0131 m_config->deleteGroup(groupName); 0132 } 0133 } 0134 0135 // now we copy all the "Tool/" groups, the "Tools", and "ToolsGUI" groups over 0136 for (const QString& groupName : stdToolConfig.groupList()) { 0137 if(groupName != SHORTCUTS_GROUP_NAME) { 0138 KConfigGroup configGroup = stdToolConfig.group(groupName); 0139 m_config->deleteGroup(groupName); 0140 KConfigGroup newGroup = m_config->group(groupName); 0141 configGroup.copyTo(&newGroup, KConfigGroup::Persistent); 0142 } 0143 } 0144 } 0145 0146 static void transferKeyStringPairsStartingWith(KConfigGroup& src, KConfigGroup& target, const QString& startsWith) 0147 { 0148 const QStringList keyList = src.keyList(); 0149 for (const QString& key : keyList) { 0150 if(key.startsWith(startsWith)) { 0151 QString value = src.readEntry(key, QString()); 0152 target.writeEntry(key, value); 0153 } 0154 } 0155 } 0156 0157 void Factory::installStandardLivePreviewTools() 0158 { 0159 KConfig stdToolConfig(m_standardToolConfigurationFileName, KConfig::NoGlobals); 0160 0161 const QStringList groupList = stdToolConfig.groupList(); 0162 for (const QString& groupName : groupList) { 0163 if(groupName.startsWith(QStringLiteral("Tool/LivePreview"))) { 0164 KConfigGroup configGroup = stdToolConfig.group(groupName); 0165 m_config->deleteGroup(groupName); 0166 KConfigGroup newGroup = m_config->group(groupName); 0167 configGroup.copyTo(&newGroup, KConfigGroup::Persistent); 0168 } 0169 } 0170 0171 { // transfer the standard settings inside the "Tools" group 0172 const QString groupName(QStringLiteral("Tools")); 0173 KConfigGroup stdConfigGroup = stdToolConfig.group(groupName); 0174 KConfigGroup newGroup = m_config->group(groupName); 0175 transferKeyStringPairsStartingWith(stdConfigGroup, newGroup, QStringLiteral("LivePreview")); 0176 } 0177 0178 { // transfer the standard settings inside the "ToolsGUI" group 0179 const QString groupName(QStringLiteral("ToolsGUI")); 0180 KConfigGroup stdConfigGroup = stdToolConfig.group(groupName); 0181 KConfigGroup newGroup = m_config->group(groupName); 0182 transferKeyStringPairsStartingWith(stdConfigGroup, newGroup, QStringLiteral("LivePreview")); 0183 } 0184 } 0185 0186 /////////////// LaTeX //////////////// 0187 0188 LaTeX::LaTeX(const QString& tool, Manager *mngr, bool prepare) 0189 : Compile(tool, mngr, prepare), m_latexOutputHandler(Q_NULLPTR) 0190 { 0191 } 0192 0193 LaTeX::~LaTeX() 0194 { 0195 } 0196 0197 void LaTeX::setupAsChildTool(KileTool::Base *child) 0198 { 0199 KileTool::LaTeX *latexChild = dynamic_cast<KileTool::LaTeX*>(child); 0200 if(latexChild) { 0201 latexChild->setLaTeXOutputHandler(latexOutputHandler()); 0202 } 0203 } 0204 0205 LaTeXOutputHandler* LaTeX::latexOutputHandler() 0206 { 0207 return m_latexOutputHandler; 0208 } 0209 0210 void LaTeX::setLaTeXOutputHandler(LaTeXOutputHandler *h) 0211 { 0212 m_latexOutputHandler = h; 0213 } 0214 0215 bool LaTeX::determineSource() 0216 { 0217 QString src = source(); 0218 0219 // check whether the source has been set already 0220 if(!src.isEmpty()) { 0221 return true; 0222 } 0223 0224 //the basedir is determined from the current compile target 0225 //determined by getCompileName() 0226 LaTeXOutputHandler *h = Q_NULLPTR; 0227 src = m_ki->getCompileName(false, &h); 0228 0229 setSource(src); 0230 setLaTeXOutputHandler(h); 0231 0232 return true; 0233 } 0234 0235 int LaTeX::m_reRun = 0; 0236 0237 // FIXME don't hardcode bbl and ind suffix here. 0238 bool LaTeX::updateBibs(bool checkOnlyBibDependencies) 0239 { 0240 KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); 0241 if(docinfo) { 0242 QFileInfo fileinfo(docinfo->url().toLocalFile()); 0243 QStringList dependencies; 0244 0245 if (checkOnlyBibDependencies) { 0246 dependencies = manager()->info()->allBibliographies(docinfo); 0247 } 0248 else { 0249 dependencies = manager()->info()->allDependencies(docinfo); 0250 dependencies.append(fileinfo.fileName()); 0251 } 0252 if (!dependencies.empty()) { 0253 return needsUpdate(targetDir() + '/' + S() + ".bbl", 0254 KileUtilities::lastModifiedFile(dependencies, fileinfo.absolutePath())); 0255 } 0256 } 0257 0258 return false; 0259 } 0260 0261 bool LaTeX::updateIndex() 0262 { 0263 KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); 0264 if(docinfo) { 0265 QStringList pckgs = manager()->info()->allPackages(docinfo); 0266 if(pckgs.contains("makeidx") || pckgs.contains("imakeidx") || pckgs.contains("splitidx")) { 0267 return needsUpdate(targetDir() + '/' + S() + ".ind", manager()->info()->lastModifiedFile(docinfo)); 0268 } 0269 } 0270 0271 return false; 0272 } 0273 0274 bool LaTeX::updateAsy() 0275 { 0276 KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); 0277 if(docinfo) { 0278 QStringList pckgs = manager()->info()->allPackages(docinfo); 0279 // As asymptote doesn't properly notify the user when it needs to be rerun, we run 0280 // it every time LaTeX is run (but only for m_reRun == 0 if LaTeX has to be rerun). 0281 if(pckgs.contains("asymptote")) { 0282 return true; 0283 } 0284 } 0285 return false; 0286 } 0287 0288 bool LaTeX::finish(int r) 0289 { 0290 KILE_DEBUG_MAIN << "==bool LaTeX::finish(" << r << ")====="; 0291 0292 m_toolResult = r; 0293 0294 if(m_toolResult == AbnormalExit || m_toolResult == Aborted) { 0295 return false; 0296 } 0297 0298 // in case the compilation failed, we try to parse the log file in order to detect 0299 // errors reported by LaTeX 0300 QString log = targetDir() + '/' + S() + ".log"; 0301 manager()->parserManager()->parseOutput(this, log, source()); 0302 0303 return true; 0304 } 0305 0306 void LaTeX::latexOutputParserResultInstalled() 0307 { 0308 KILE_DEBUG_MAIN; 0309 0310 if(m_latexOutputHandler) { 0311 m_latexOutputHandler->storeLaTeXOutputParserResult(m_nErrors, m_nWarnings, m_nBadBoxes, m_latexOutputInfoList, 0312 m_logFile); 0313 } 0314 0315 checqCriticals(); 0316 0317 if(readEntry("autoRun") == "yes") { 0318 checkAutoRun(); 0319 } 0320 0321 Compile::finish(m_toolResult); 0322 } 0323 0324 void LaTeX::checqCriticals() 0325 { 0326 // work around the 0 cases as the i18np call can cause some confusion when 0 is passed to it (#275700) 0327 QString es = (m_nErrors == 0 ? i18n("0 errors") : i18np("1 error", "%1 errors", m_nErrors)); 0328 QString ws = (m_nWarnings == 0 ? i18n("0 warnings") : i18np("1 warning", "%1 warnings", m_nWarnings)); 0329 QString bs = (m_nBadBoxes == 0 ? i18n("0 badboxes") : i18np("1 badbox", "%1 badboxes", m_nBadBoxes)); 0330 0331 sendMessage(Info, i18nc("String displayed in the log panel showing the number of errors/warnings/badboxes", 0332 "%1, %2, %3", es, ws, bs)); 0333 0334 // jump to first error 0335 if(!isPartOfLivePreview() && m_nErrors > 0 && (readEntry("jumpToFirstError") == "yes")) { 0336 connect(this, SIGNAL(jumpToFirstError()), manager(), SIGNAL(jumpToFirstError())); 0337 emit(jumpToFirstError()); 0338 } 0339 } 0340 0341 void LaTeX::configureLaTeX(KileTool::Base *tool, const QString& source) 0342 { 0343 tool->setSource(source, workingDir()); 0344 } 0345 0346 void LaTeX::configureBibTeX(KileTool::Base *tool, const QString& source) 0347 { 0348 tool->setSource(source, workingDir()); 0349 } 0350 0351 void LaTeX::configureMakeIndex(KileTool::Base *tool, const QString& source) 0352 { 0353 tool->setSource(source, workingDir()); 0354 } 0355 0356 void LaTeX::configureAsymptote(KileTool::Base *tool, const QString& source) 0357 { 0358 tool->setSource(source, workingDir()); 0359 } 0360 0361 // if 'Biblatex' is not used in the document, 'hint' will be empty 0362 ToolConfigPair LaTeX::determineBibliographyBackend(const QString& hint) 0363 { 0364 if(m_latexOutputHandler) { 0365 ToolConfigPair userBibTool = m_latexOutputHandler->bibliographyBackendToolUserOverride(); 0366 0367 if(userBibTool.isValid()) { 0368 // now we still check whether such a tool really exists 0369 if (manager()->containsBibliographyTool(userBibTool)) { 0370 return userBibTool; 0371 } 0372 else { 0373 KILE_DEBUG_MAIN << "Cannot find the following bibtool set by the user:" << userBibTool; 0374 KILE_DEBUG_MAIN << "trying to auto-detect it now!"; 0375 sendMessage(Warning, i18n("Manually selected bibliography tool does not exist: trying to " 0376 "auto-detect it now.")); 0377 } 0378 } 0379 } 0380 0381 // we will now try to detect the bib tool by using the given command hint 0382 ToolConfigPair bibTool = manager()->findFirstBibliographyToolForCommand(hint); 0383 0384 if(m_latexOutputHandler) { 0385 // if we managed to detect a backend, store (or update) it for future runs 0386 if(bibTool.isValid()) { 0387 m_latexOutputHandler->setBibliographyBackendToolAutoDetected(bibTool); 0388 } 0389 else { 0390 // perhaps we have it stored from a previous run? 0391 bibTool = m_latexOutputHandler->bibliographyBackendToolAutoDetected(); 0392 // perhaps the bib tools have changed from the previous run? 0393 if (!manager()->containsBibliographyTool(bibTool)) { 0394 bibTool = ToolConfigPair(); 0395 } 0396 } 0397 } 0398 0399 // this tool must always be available 0400 const ToolConfigPair defaultBibTool = ToolConfigPair(QString("BibTeX"), DEFAULT_TOOL_CONFIGURATION); 0401 0402 // if no tool has been detected, the default is BibTeX 0403 return bibTool.isValid() ? bibTool : defaultBibTool; 0404 } 0405 0406 void LaTeX::checkAutoRun() 0407 { 0408 KILE_DEBUG_MAIN << "check for autorun, m_reRun is " << m_reRun; 0409 if(m_reRun >= 2) { 0410 KILE_DEBUG_MAIN << "Already rerun twice, doing nothing."; 0411 m_reRun = 0; 0412 return; 0413 } 0414 if(m_nErrors > 0) { 0415 KILE_DEBUG_MAIN << "Errors found, not running again."; 0416 m_reRun = 0; 0417 return; 0418 } 0419 bool reRunWarningFound = false; 0420 QString bibToolInLaTexOutput; 0421 bool haveUndefinedCitations = false; 0422 // check for "rerun" LaTeX and other tools warnings 0423 if(m_nWarnings > 0) { 0424 int sz = m_latexOutputInfoList.size(); 0425 // the messages we are looking for are the last ones (most likely the very last one), so go from end to beginning 0426 for(int i = sz-1; i >= 0; --i) { 0427 if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning 0428 && m_latexOutputInfoList[i].message().contains("Rerun", Qt::CaseInsensitive)) { 0429 // the message could be a message from Biblatex like this: 0430 // Package biblatex Warning: The following entry could not be found 0431 // (biblatex) in the database: 0432 // (biblatex) <entry_name> 0433 // (biblatex) Please verify the spelling and rerun 0434 // (biblatex) LaTeX afterwards. 0435 // 0436 // our strategy: if the warning message contains "(biblatex)", Biblatex only 0437 // suggests to check the source files first, but not to recompile yet 0438 if (!m_latexOutputInfoList[i].message().contains("(biblatex)", Qt::CaseInsensitive)) { 0439 reRunWarningFound = true; 0440 break; 0441 } 0442 } 0443 } 0444 // Now look for messages from Biblatex like the following: 0445 // Please (re)run Biber on the file: 0446 // or 0447 // Please (re)run Bibtex on the file: 0448 QRegExp biblatexBackendMessage = QRegExp(".*Please \\(re\\)run ([A-Za-z]+) on the file", Qt::CaseInsensitive); 0449 for(int i = sz-1; i >= 0; --i) { // same here, start from the end 0450 if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning 0451 && biblatexBackendMessage.indexIn(m_latexOutputInfoList[i].message()) != -1) { 0452 bibToolInLaTexOutput = biblatexBackendMessage.cap(1); 0453 KILE_DEBUG_MAIN << "Captured Bib tool: " << bibToolInLaTexOutput; 0454 break; 0455 } 0456 } 0457 // If we did not get a message from Biblatex about bibtool (re)run, then 0458 // we look for messages like "LaTeX Warning: Citation `A' on page 234 undefined on input line 12345." 0459 // In that case we probably need to (re)run the bibtool. 0460 if (bibToolInLaTexOutput.isEmpty()) { 0461 QRegExp citationUndefinedMessage = QRegExp("Citation `(.+)' on page (\\d+) undefined on input line (\\d+)", 0462 Qt::CaseInsensitive); 0463 for(int i = 0; i < sz; ++i) { 0464 if (m_latexOutputInfoList[i].type() == LatexOutputInfo::itmWarning 0465 && citationUndefinedMessage.indexIn(m_latexOutputInfoList[i].message()) != -1) { 0466 haveUndefinedCitations = true; 0467 KILE_DEBUG_MAIN << "Detected undefined citations"; 0468 break; 0469 } 0470 } 0471 } 0472 } 0473 0474 bool asy = (m_reRun == 0) && updateAsy(); 0475 // We run bibtool in the following cases: 0476 // 1. Biblatex said that we have to (in this case bibToolInLaTexOutput is not empty), OR 0477 // 2. There are no undefined citations and at least one of the .bib files has a younger modification 0478 // date than the .bbl file, OR 0479 // 3. We have undefined citations and at least one of the source files (including .bib and .tex) is 0480 // younger than .bbl. 0481 // (If the .bbl file is younger than all of them, the next rerun will not change anything) 0482 bool bibs = !bibToolInLaTexOutput.isEmpty() || updateBibs(!haveUndefinedCitations); 0483 bool index = updateIndex(); 0484 KILE_DEBUG_MAIN << "asy:" << asy << "bibs:" << bibs << "index:" << index << "reRunWarningFound:" << reRunWarningFound; 0485 // Currently, we don't properly detect yet whether asymptote has to be run. 0486 // So, if asymtote figures are present, we run it each time after the first LaTeX run. 0487 bool reRun = (asy || bibs || index || reRunWarningFound); 0488 KILE_DEBUG_MAIN << "reRun:" << reRun; 0489 0490 if(reRun) { 0491 KILE_DEBUG_MAIN << "rerunning LaTeX, m_reRun is now " << m_reRun; 0492 Base *tool = manager()->createTool(name(), toolConfig()); 0493 if(tool) { 0494 configureLaTeX(tool, source()); 0495 // e.g. for LivePreview, it is necessary that the paths are copied to child processes 0496 tool->copyPaths(this); 0497 runChildNext(tool); 0498 m_reRun++; 0499 } 0500 } 0501 else { 0502 m_reRun = 0; 0503 } 0504 0505 if(bibs) { 0506 KILE_DEBUG_MAIN << "need to run the bibliography tool " << bibToolInLaTexOutput; 0507 ToolConfigPair bibTool = determineBibliographyBackend(bibToolInLaTexOutput); 0508 Base *tool = manager()->createTool(bibTool.first, bibTool.second); 0509 if(tool) { 0510 configureBibTeX(tool, targetDir() + '/' + S() + '.' + tool->from()); 0511 // e.g. for LivePreview, it is necessary that the paths are copied to child processes 0512 tool->copyPaths(this); 0513 runChildNext(tool); 0514 } 0515 } 0516 0517 if(index) { 0518 KILE_DEBUG_MAIN << "need to run MakeIndex"; 0519 Base *tool = manager()->createTool("MakeIndex", QString()); 0520 if(tool) { 0521 KILE_DEBUG_MAIN << targetDir() << S() << tool->from(); 0522 configureMakeIndex(tool, targetDir() + '/' + S() + '.' + tool->from()); 0523 // e.g. for LivePreview, it is necessary that the paths are copied to child processes 0524 tool->copyPaths(this); 0525 runChildNext(tool); 0526 } 0527 } 0528 0529 if(asy) { 0530 KILE_DEBUG_MAIN << "need to run asymptote"; 0531 int sz = manager()->info()->allAsyFigures().size(); 0532 for(int i = sz -1; i >= 0; --i) { 0533 Base *tool = manager()->createTool("Asymptote", QString()); 0534 0535 if(tool) { 0536 configureAsymptote(tool, targetDir() + '/' + S() + '-' + QString::number(i + 1) + '.' + tool->from()); 0537 // e.g. for LivePreview, it is necessary that the paths are copied to child processes 0538 tool->copyPaths(this); 0539 runChildNext(tool); 0540 } 0541 } 0542 } 0543 } 0544 0545 0546 /////////////// PreviewLaTeX (dani) //////////////// 0547 0548 PreviewLaTeX::PreviewLaTeX(const QString& tool, Manager *mngr, bool prepare) : LaTeX(tool, mngr, prepare) 0549 { 0550 } 0551 0552 // PreviewLatex makes three steps: 0553 // - filterLogfile() : parse logfile and read info into InfoLists 0554 // - updateInfoLists(): change entries of temporary file into normal tex file 0555 // - checqCriticals() : count errors and warnings and emit signals 0556 bool PreviewLaTeX::finish(int r) 0557 { 0558 KILE_DEBUG_MAIN << r; 0559 0560 m_toolResult = r; 0561 0562 if(r != Success) { 0563 return Compile::finish(r); 0564 } 0565 0566 QString log = targetDir() + '/' + S() + ".log"; 0567 manager()->parserManager()->parseOutput(this, log, source(), m_filename, m_selrow, m_docrow); 0568 0569 return true; 0570 } 0571 0572 void PreviewLaTeX::setPreviewInfo(const QString &filename, int selrow,int docrow) 0573 { 0574 m_filename = filename; 0575 m_selrow = selrow; 0576 m_docrow = docrow; 0577 } 0578 0579 /////////////// LivePreviewLaTeX //////////////// 0580 0581 LivePreviewLaTeX::LivePreviewLaTeX(const QString& tool, Manager *mngr, bool prepare) 0582 : LaTeX(tool, mngr, prepare) 0583 { 0584 } 0585 0586 void LivePreviewLaTeX::configureLaTeX(KileTool::Base *tool, const QString& source) 0587 { 0588 LaTeX::configureLaTeX(tool, source); 0589 tool->setTargetDir(targetDir()); 0590 } 0591 0592 void LivePreviewLaTeX::configureBibTeX(KileTool::Base *tool, const QString& source) 0593 { 0594 tool->setSource(source, targetDir()); 0595 } 0596 0597 void LivePreviewLaTeX::configureMakeIndex(KileTool::Base *tool, const QString& source) 0598 { 0599 tool->setSource(source, targetDir()); 0600 } 0601 0602 void LivePreviewLaTeX::configureAsymptote(KileTool::Base *tool, const QString& source) 0603 { 0604 tool->setSource(source, targetDir()); 0605 } 0606 // PreviewLatex makes three steps: 0607 // - filterLogfile() : parse logfile and read info into InfoLists 0608 // - updateInfoLists(): change entries of temporary file into normal tex file 0609 // - checqCriticals() : count errors and warnings and emit signals 0610 // bool LivePreviewLaTeX::finish(int r) 0611 // { 0612 // KILE_DEBUG_MAIN << "==bool PreviewLaTeX::finish(" << r << ")====="; 0613 // 0614 // int nErrors = 0, nWarnings = 0; 0615 // if(filterLogfile()) { 0616 // manager()->info()->outputFilter()->updateInfoLists(m_filename,m_selrow,m_docrow); 0617 // checqCriticals(nErrors,nWarnings); 0618 // } 0619 // 0620 // return Compile::finish(r); 0621 // } 0622 // 0623 // void LivePreviewLaTeX::setPreviewInfo(const QString &filename, int selrow,int docrow) 0624 // { 0625 // m_filename = filename; 0626 // m_selrow = selrow; 0627 // m_docrow = docrow; 0628 // } 0629 0630 0631 ForwardDVI::ForwardDVI(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) 0632 { 0633 } 0634 0635 bool ForwardDVI::checkPrereqs () 0636 { 0637 KProcess okularVersionTester; 0638 okularVersionTester.setOutputChannelMode(KProcess::MergedChannels); 0639 okularVersionTester.setProgram("okular", QStringList("--version")); 0640 okularVersionTester.start(); 0641 0642 if (okularVersionTester.waitForFinished()) { 0643 QString output = okularVersionTester.readAll(); 0644 QRegExp regExp = QRegExp("Okular: (\\d+).(\\d+).(\\d+)"); 0645 0646 if(output.contains(regExp)) { 0647 int majorVersion = regExp.cap(1).toInt(); 0648 int minorVersion = regExp.cap(2).toInt(); 0649 int veryMinorVersion = regExp.cap(3).toInt(); 0650 0651 // see https://mail.kde.org/pipermail/okular-devel/2009-May/003741.html 0652 // the required okular version is > 0.8.5 0653 if( majorVersion > 0 || 0654 ( majorVersion == 0 && minorVersion > 8 ) || 0655 ( majorVersion == 0 && minorVersion == 8 && veryMinorVersion > 5 ) ) { 0656 ; // everything okay 0657 } 0658 else { 0659 sendMessage(Error,i18n("The version %1.%2.%3 of okular is too old for ForwardDVI. Please update okular to version 0.8.6 or higher",majorVersion,minorVersion,veryMinorVersion)); 0660 } 0661 } 0662 } 0663 // don't return false here because we don't know for sure if okular is used 0664 return true; 0665 } 0666 0667 bool ForwardDVI::determineTarget() 0668 { 0669 if (!View::determineTarget()) { 0670 return false; 0671 } 0672 0673 int para = manager()->info()->lineNumber(); 0674 KTextEditor::Document *doc = manager()->info()->activeTextDocument(); 0675 0676 if (!doc) { 0677 return false; 0678 } 0679 0680 QString filepath = doc->url().toLocalFile(); 0681 QString texfile = QDir(baseDir()).relativeFilePath(filepath); 0682 QString relativeTarget = "file:" + targetDir() + '/' + target() + "#src:" + QString::number(para + 1) + ' ' + texfile; // space added, for files starting with numbers 0683 QString absoluteTarget = "file:" + targetDir() + '/' + target() + "#src:" + QString::number(para + 1) + filepath; 0684 0685 if(readEntry("type") == "DocumentViewer") { 0686 addDict("%dir_target", targetDir()); 0687 addDict("%target", target()); 0688 addDict("%sourceFileName", filepath); 0689 addDict("%sourceLine", QString::number(para + 1)); 0690 } 0691 else { 0692 addDict("%dir_target", QString()); 0693 addDict("%target", relativeTarget); 0694 } 0695 0696 addDict("%absolute_target", absoluteTarget); 0697 KILE_DEBUG_MAIN << "==KileTool::ForwardDVI::determineTarget()=============\n"; 0698 KILE_DEBUG_MAIN << "\tusing (absolute)" << absoluteTarget; 0699 KILE_DEBUG_MAIN << "\tusing (relative)" << relativeTarget; 0700 0701 return true; 0702 } 0703 0704 ViewBib::ViewBib(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) 0705 { 0706 } 0707 0708 bool ViewBib::determineSource() 0709 { 0710 KILE_DEBUG_MAIN << "==ViewBib::determineSource()======="; 0711 if (!View::determineSource()) { 0712 return false; 0713 } 0714 0715 QString path = source(true); 0716 QFileInfo info(path); 0717 0718 //get the bibliographies for this source 0719 QStringList bibs = manager()->info()->allBibliographies(manager()->info()->docManager()->textInfoFor(path)); 0720 KILE_DEBUG_MAIN << "\tfound " << bibs.count() << " bibs"; 0721 if(bibs.count() > 0) { 0722 QString bib = bibs.front(); 0723 if (bibs.count() > 1) { 0724 //show dialog 0725 bool bib_selected = false; 0726 KileListSelector *dlg = new KileListSelector(bibs, i18n("Select Bibliography"),i18n("Select a bibliography")); 0727 if (dlg->exec() && dlg->hasSelection()) { 0728 bib = dlg->selectedItems().first(); 0729 bib_selected = true; 0730 KILE_DEBUG_MAIN << "Bibliography selected : " << bib; 0731 } 0732 delete dlg; 0733 0734 if(!bib_selected) { 0735 sendMessage(Warning, i18n("No bibliography selected.")); 0736 return false; 0737 } 0738 } 0739 KILE_DEBUG_MAIN << "filename before: " << info.path(); 0740 setSource(manager()->info()->checkOtherPaths(info.path(),bib + ".bib",KileInfo::bibinputs)); 0741 } 0742 else if(info.exists()) { //active doc is a bib file 0743 KILE_DEBUG_MAIN << "filename before: " << info.path(); 0744 setSource(manager()->info()->checkOtherPaths(info.path(),info.fileName(),KileInfo::bibinputs)); 0745 } 0746 else { 0747 sendMessage(Error, i18n("No bibliographies found.")); 0748 return false; 0749 } 0750 return true; 0751 } 0752 0753 ViewHTML::ViewHTML(const QString& tool, Manager *mngr, bool prepare) : View(tool, mngr, prepare) 0754 { 0755 } 0756 0757 bool ViewHTML::determineTarget() 0758 { 0759 if (target().isNull()) { 0760 //setRelativeBaseDir(S()); 0761 QString dir = readEntry("relDir"); 0762 QString trg = readEntry("target"); 0763 0764 if(!dir.isEmpty()) { 0765 translate(dir); 0766 setRelativeBaseDir(dir); 0767 } 0768 0769 if(!trg.isEmpty()) { 0770 translate(trg); 0771 setTarget(trg); 0772 } 0773 0774 //auto-detect the file to view 0775 if(dir.isEmpty() && trg.isEmpty()) { 0776 QFileInfo file1 = QFileInfo(baseDir() + '/' + S() + QLatin1String("/index.html")); 0777 QFileInfo file2 = QFileInfo(baseDir() + '/' + S() + QLatin1String(".html")); 0778 0779 bool read1 = file1.isReadable(); 0780 bool read2 = file2.isReadable(); 0781 0782 if(!read1 && !read2) { 0783 sendMessage(Error, i18n("Unable to find %1 or %2; if you are trying to view some other HTML file, go to Settings->Configure Kile->Tools->ViewHTML->Advanced.", file1.absoluteFilePath(), file2.absoluteFilePath())); 0784 return false; 0785 } 0786 0787 //both exist, take most recent 0788 if(read1 && read2) { 0789 read1 = file1.lastModified() > file2.lastModified(); 0790 read2 = !read1; 0791 } 0792 0793 if(read1) { 0794 dir = S(); 0795 trg = "index.html"; 0796 } 0797 else if(read2) { 0798 dir = QLatin1String("."); 0799 trg = S() + QLatin1String(".html"); 0800 } 0801 0802 translate(dir); 0803 setRelativeBaseDir(dir); 0804 translate(trg); 0805 setTarget(trg); 0806 0807 } 0808 } 0809 0810 return View::determineTarget(); 0811 } 0812 } 0813 0814 /* 0815 * BibliographyCompile 0816 */ 0817 0818 const QString KileTool::BibliographyCompile::ToolClass = "Bibliography"; 0819 0820 KileTool::BibliographyCompile::BibliographyCompile(const QString& name, KileTool::Manager* manager, bool prepare) 0821 : Compile(name, manager, prepare) 0822 { 0823 0824 } 0825 0826 0827