File indexing completed on 2024-04-14 15:17:39
0001 /*************************************************************************** 0002 Copyright (C) 2003 by Jeroen Wijnhout (jeroen.wijnhout@kdemail.net) 0003 2010-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 "kiletool.h" 0016 0017 #include <QDir> 0018 #include <QFileInfo> 0019 #include <QMetaObject> 0020 #include <QRegExp> 0021 #include <QTimer> 0022 0023 #include <KConfig> 0024 #include <KLocalizedString> 0025 #include <KShell> 0026 #include <QUrl> 0027 0028 #include "kileconfig.h" 0029 #include "kiletool_enums.h" 0030 #include "kilestdtools.h" //for the factory 0031 #include "kiletoolmanager.h" 0032 #include "kiledocmanager.h" 0033 #include "kileinfo.h" 0034 #include "documentinfo.h" 0035 #include "kileproject.h" 0036 0037 namespace KileTool 0038 { 0039 Base::Base(const QString &name, Manager *manager, bool prepare /* = true */) : 0040 QObject(manager), // ensure that they are deleted whenever the tool manager gets deleted 0041 m_launcher(Q_NULLPTR), 0042 m_quickie(false), 0043 m_isPartOfLivePreview(false), 0044 m_manager(manager), 0045 m_name(name), 0046 m_bPrepareToRun(prepare), 0047 m_texInputs(KileConfig::teXPaths()), 0048 m_bibInputs(KileConfig::bibInputPaths()), 0049 m_bstInputs(KileConfig::bstInputPaths()), 0050 m_childToolSpawned(false), 0051 m_toolResult(-1) 0052 { 0053 // WARNING: 'NeedSaveAll' is currently needed to indicate to the tool manager that parsing has to be finished 0054 // before it launches this tool! This is important to ensure that the right master document is used 0055 // in the case of projects, for example. 0056 m_flags = NeedTargetDirExec | NeedTargetDirWrite | NeedActiveDoc | NeedMasterDoc | NoUntitledDoc | NeedSourceExists | NeedSourceRead | NeedSaveAll; 0057 0058 setMsg(NeedTargetDirExec, ki18n("Could not change to the folder %1.")); 0059 setMsg(NeedTargetDirWrite, ki18n("The folder %1 is not writable, therefore %2 will not be able to save its results.")); 0060 setMsg(NeedTargetExists, ki18n("The file %1/%2 does not exist. If this is unexpected, check the file permissions.")); 0061 setMsg(NeedTargetRead, ki18n("The file %1/%2 is not readable. If this is unexpected, check the file permissions.")); 0062 setMsg(NeedActiveDoc, ki18n("Could not determine on which file to run %1, because there is no active document.")); 0063 setMsg(NeedMasterDoc, ki18n("Could not determine the master file for this document.")); 0064 setMsg(NoUntitledDoc, ki18n("Please save the untitled document first.")); 0065 setMsg(NeedSourceExists, ki18n("The file %1 does not exist.")); 0066 setMsg(NeedSourceRead, ki18n("The file %1 is not readable.")); 0067 0068 m_bPrepared = false; 0069 } 0070 0071 Base::~Base() 0072 { 0073 KILE_DEBUG_MAIN << "DELETING TOOL: " << name() << this; 0074 emit(aboutToBeDestroyed(this)); 0075 delete m_launcher; 0076 } 0077 0078 QString Base::source(bool absolute /* = true */) const 0079 { 0080 if (m_source.isEmpty()) { 0081 return QString(); 0082 } 0083 0084 QString src = m_source; 0085 if (absolute) { 0086 src = m_basedir + '/' + src; 0087 } 0088 0089 return src; 0090 } 0091 0092 void Base::setMsg(long n, const KLocalizedString& msg) 0093 { 0094 m_messages[n] = msg; 0095 } 0096 0097 void Base::translate(QString &str, bool quoteForShell) 0098 { 0099 QHashIterator<QString,QString> it(paramDict()); 0100 while(it.hasNext()) { 0101 it.next(); 0102 QString value; 0103 // the file names in %AFL are quoted already 0104 if(quoteForShell && it.key() != "%AFL") { 0105 value = KShell::quoteArg(it.value()); 0106 } 0107 else { 0108 value = it.value(); 0109 } 0110 str.replace(it.key(), value); 0111 } 0112 } 0113 0114 void Base::removeFlag(uint flag) 0115 { 0116 m_flags &= ~flag; 0117 } 0118 0119 0120 bool Base::requestSaveAll() 0121 { 0122 return (flags() & NeedSaveAll); 0123 } 0124 0125 void Base::setEntry(const QString& key, const QString& value) 0126 { 0127 m_entryMap[key] = value; 0128 } 0129 0130 void Base::prepareToRun() 0131 { 0132 KILE_DEBUG_MAIN << "==Base::prepareToRun()======="; 0133 0134 //install a launcher 0135 if (!installLauncher()) 0136 { 0137 m_nPreparationResult = NoLauncherInstalled; 0138 m_bPrepared = false; 0139 return; 0140 } 0141 0142 if (!determineSource()) 0143 { 0144 m_nPreparationResult = NoValidSource; 0145 m_bPrepared = false; 0146 return; 0147 } 0148 0149 if (!determineTarget()) 0150 { 0151 m_nPreparationResult = NoValidTarget; 0152 m_bPrepared = false; 0153 return; 0154 } 0155 0156 if ( m_launcher == 0 ) 0157 { 0158 m_nPreparationResult = NoLauncherInstalled; 0159 m_bPrepared = false; 0160 return; 0161 } 0162 0163 if(!workingDir().isEmpty()) { 0164 m_launcher->setWorkingDirectory(workingDir()); 0165 } 0166 else { 0167 m_launcher->setWorkingDirectory(baseDir()); 0168 } 0169 0170 //fill in the dictionary 0171 addDict("%options", m_options); 0172 0173 m_resolution = KileConfig::dvipngResolution() ; 0174 addDict("%res",m_resolution); 0175 0176 m_bPrepared = true; 0177 m_nPreparationResult = Running; 0178 } 0179 0180 int Base::run() 0181 { 0182 KILE_DEBUG_MAIN << "==KileTool::Base::run()================="; 0183 0184 if(m_nPreparationResult != 0) { 0185 emit(failedToRun(this, m_nPreparationResult)); 0186 return m_nPreparationResult; 0187 } 0188 0189 if(!checkSource()) { 0190 emit(failedToRun(this, NoValidSource)); 0191 return NoValidSource; 0192 } 0193 0194 if(!checkTarget()) { 0195 emit(failedToRun(this, TargetHasWrongPermissions)); 0196 return TargetHasWrongPermissions; 0197 } 0198 0199 if (!checkPrereqs()) { 0200 emit(failedToRun(this, NoValidPrereqs)); 0201 return NoValidPrereqs; 0202 } 0203 0204 emit(start(this)); 0205 0206 if (!m_launcher || !m_launcher->launch()) { 0207 KILE_DEBUG_MAIN << "\tlaunching failed"; 0208 if(!m_launcher) { 0209 emit(failedToRun(this, CouldNotLaunch)); 0210 return CouldNotLaunch; 0211 } 0212 if(!m_launcher->selfCheck()) { 0213 emit(failedToRun(this, SelfCheckFailed)); 0214 return SelfCheckFailed; 0215 } 0216 else { 0217 emit(failedToRun(this, CouldNotLaunch)); 0218 return CouldNotLaunch; 0219 } 0220 } 0221 0222 KILE_DEBUG_MAIN << "\trunning..."; 0223 0224 return Running; 0225 0226 } 0227 0228 bool Base::determineSource() 0229 { 0230 QString src = source(); 0231 0232 // check whether the source has been set already 0233 if(!src.isEmpty()) { 0234 return true; 0235 } 0236 0237 //the basedir is determined from the current compile target 0238 //determined by getCompileName() 0239 if(src.isEmpty()) { 0240 src = m_ki->getCompileName(); 0241 } 0242 setSource(src); 0243 0244 return true; 0245 } 0246 0247 bool Base::checkSource() 0248 { 0249 //FIXME deal with tools that do not need a source or target (yes they exist) 0250 //Is there an active document? Only check if the source file is not explicitly set. 0251 if((m_source.isEmpty()) && (m_manager->info()->activeTextDocument() == Q_NULLPTR)) { 0252 sendMessage(Error, msg(NeedActiveDoc).subs(name()).toString()); 0253 return false; 0254 } 0255 0256 if(m_source.isEmpty() && m_manager->info()->activeTextDocument() != Q_NULLPTR) { 0257 if(m_manager->info()->activeTextDocument()->url().isEmpty() 0258 && (flags() & NoUntitledDoc)) { 0259 sendMessage(Error, msg(NoUntitledDoc).toString()); 0260 return false; 0261 } 0262 else { 0263 //couldn't find a source file, huh? 0264 //we know there is an active document, the only reason is could have failed is because 0265 //we couldn't find a LaTeX root document 0266 sendMessage(Error, msg(NeedMasterDoc).toString()); 0267 return false; 0268 } 0269 } 0270 0271 QFileInfo fi(source()); 0272 if((flags() & NeedSourceExists) && !fi.exists()) { 0273 sendMessage(Error, msg(NeedSourceExists).subs(fi.absoluteFilePath()).toString()); 0274 return false; 0275 } 0276 0277 if((flags() & NeedSourceRead) && !fi.isReadable()) { 0278 sendMessage(Error, msg(NeedSourceRead).subs(fi.absoluteFilePath()).toString()); 0279 return false; 0280 } 0281 0282 return true; 0283 } 0284 0285 void Base::runChildNext(Base *tool, bool block /*= false*/) 0286 { 0287 m_childToolSpawned = true; 0288 if(isPartOfLivePreview()) { 0289 tool->setPartOfLivePreview(); 0290 } 0291 manager()->runChildNext(this, tool, block); 0292 } 0293 0294 void Base::setSource(const QString &source, const QString& workingDir) 0295 { 0296 QFileInfo info(source); 0297 0298 if(!from().isEmpty()) { 0299 QString src = source; 0300 if(info.suffix().length() > 0) { 0301 src.replace(QRegExp(info.suffix() + '$'), from()); 0302 } 0303 info.setFile(src); 0304 } 0305 0306 if(!workingDir.isEmpty()) { 0307 setWorkingDir(workingDir); 0308 } 0309 0310 m_basedir = info.absolutePath(); 0311 m_source = info.fileName(); 0312 m_S = info.completeBaseName(); 0313 0314 addDict("%dir_base", m_basedir); 0315 addDict("%source", m_source); 0316 addDict("%S",m_S); 0317 0318 KILE_DEBUG_MAIN << "===KileTool::Base::setSource()=============="; 0319 KILE_DEBUG_MAIN << "using " << source; 0320 KILE_DEBUG_MAIN << "source="<<m_source; 0321 KILE_DEBUG_MAIN << "S=" << m_S; 0322 KILE_DEBUG_MAIN << "basedir=" << m_basedir; 0323 KILE_DEBUG_MAIN << "workingDir=" << m_workingDir; 0324 } 0325 0326 void Base::setTeXInputPaths(const QString& s) 0327 { 0328 m_texInputs = s; 0329 } 0330 0331 QString Base::teXInputPaths() const 0332 { 0333 return m_texInputs; 0334 } 0335 0336 void Base::setBibInputPaths(const QString& s) 0337 { 0338 m_bibInputs = s; 0339 } 0340 0341 QString Base::bibInputPaths() const 0342 { 0343 return m_bibInputs; 0344 } 0345 0346 void Base::setBstInputPaths(const QString& s) 0347 { 0348 m_bstInputs = s; 0349 } 0350 0351 QString Base::bstInputPaths() const 0352 { 0353 return m_bstInputs; 0354 } 0355 0356 void Base::copyPaths(Base* tool) 0357 { 0358 setTeXInputPaths(tool->teXInputPaths()); 0359 setBibInputPaths(tool->bibInputPaths()); 0360 setBstInputPaths(tool->bstInputPaths()); 0361 } 0362 0363 bool Base::determineTarget() 0364 { 0365 QFileInfo info(source()); 0366 0367 //if the target is not set previously, use the source filename 0368 if(m_target.isEmpty()) { 0369 //test for explicit override 0370 if (!readEntry("target").isEmpty()) { 0371 KILE_DEBUG_MAIN << "USING target SETTING"; 0372 m_target = readEntry("target"); 0373 } 0374 else if ( to().length() > 0) { 0375 m_target = S() + '.' + to(); 0376 } 0377 else { 0378 m_target = source(false); 0379 } 0380 } 0381 0382 if(m_relativedir.isEmpty() && (!readEntry("relDir").isEmpty())) { 0383 m_relativedir = readEntry("relDir"); 0384 } 0385 0386 QUrl url; 0387 if(!m_targetdir.isEmpty()) { 0388 url = QUrl::fromLocalFile(m_targetdir); 0389 } 0390 else if(!m_workingDir.isEmpty()) { 0391 url = QUrl::fromLocalFile(m_workingDir); 0392 } 0393 else { 0394 url = QUrl::fromLocalFile(m_basedir); 0395 } 0396 url = url.adjusted(QUrl::StripTrailingSlash); 0397 url.setPath(QDir::cleanPath(url.path() + '/' + m_relativedir)); 0398 m_targetdir = url.toLocalFile(); 0399 0400 setTarget(m_target); 0401 setTargetDir(m_targetdir); 0402 0403 KILE_DEBUG_MAIN << "==KileTool::Base::determineTarget()========="; 0404 KILE_DEBUG_MAIN << "\tm_targetdir=" << m_targetdir; 0405 KILE_DEBUG_MAIN << "\tm_target=" << m_target; 0406 0407 return true; 0408 } 0409 0410 bool Base::checkTarget() 0411 { 0412 //check if the target directory is accessible 0413 QFileInfo info(m_targetdir); 0414 0415 if((flags() & NeedTargetDirExec ) && (!info.isExecutable())) { 0416 sendMessage(Error, msg(NeedTargetDirExec).subs(m_targetdir).toString()); 0417 return false; 0418 } 0419 0420 if((flags() & NeedTargetDirWrite) && (!info.isWritable())) { 0421 sendMessage(Error, msg(NeedTargetDirWrite).subs(m_targetdir).subs(m_name).toString()); 0422 return false; 0423 } 0424 0425 info.setFile(m_targetdir + '/' + m_target); 0426 0427 if((flags() & NeedTargetExists) && (!info.exists())) { 0428 sendMessage(Error, msg(NeedTargetExists).subs(m_targetdir).subs(m_target).toString()); 0429 return false; 0430 } 0431 0432 if((flags() & NeedTargetRead) && (!info.isReadable())) { 0433 sendMessage(Error, msg(NeedTargetRead).subs(m_targetdir).subs(m_target).toString()); 0434 return false; 0435 } 0436 0437 return true; 0438 } 0439 0440 void Base::setTarget(const QString &target) 0441 { 0442 m_target = target; 0443 addDict("%target", m_target); 0444 } 0445 0446 void Base::setTargetDir(const QString &target) 0447 { 0448 m_targetdir = target; 0449 addDict("%dir_target", m_targetdir); 0450 } 0451 0452 void Base::setTargetPath(const QString &target) 0453 { 0454 QFileInfo fi(target); 0455 setTarget(fi.fileName()); 0456 setTargetDir(fi.absolutePath()); 0457 } 0458 0459 bool Base::checkPrereqs() 0460 { 0461 return true; 0462 } 0463 0464 void Base::stop() 0465 { 0466 if (m_launcher) { 0467 m_launcher->kill(); 0468 } 0469 0470 emit(done(this, Aborted, m_childToolSpawned)); 0471 } 0472 0473 bool Base::finish(int result) 0474 { 0475 KILE_DEBUG_MAIN << "==KileTool::Base::finish()=============="; 0476 if (sender()) 0477 { 0478 KILE_DEBUG_MAIN << "\tcalled by " << sender()->objectName() << " " << sender()->metaObject()->className(); 0479 } 0480 0481 if ( result == Aborted ) 0482 sendMessage(Error, "Aborted"); 0483 0484 if ( result == Success ) 0485 sendMessage(Info,"Done!"); 0486 0487 KILE_DEBUG_MAIN << "\temitting done(KileTool::Base*, int) " << name(); 0488 emit(done(this, result, m_childToolSpawned)); 0489 0490 //we will only get here if the done() signal is not connected to the manager (who will destroy this object) 0491 if (result == Success) { 0492 return true; 0493 } 0494 else { 0495 return false; 0496 } 0497 } 0498 0499 void Base::installLaTeXOutputParserResult(int nErrors, int nWarnings, int nBadBoxes, const LatexOutputInfoArray& outputList, 0500 const QString& logFile) 0501 { 0502 m_nErrors = nErrors; 0503 m_nWarnings = nWarnings; 0504 m_nBadBoxes = nBadBoxes; 0505 m_latexOutputInfoList = outputList; 0506 m_logFile = logFile; 0507 0508 latexOutputParserResultInstalled(); 0509 } 0510 0511 void Base::latexOutputParserResultInstalled() 0512 { 0513 finish(Success); 0514 } 0515 0516 void Base::installLauncher(Launcher *lr) 0517 { 0518 if(m_launcher != lr) 0519 delete m_launcher; 0520 0521 m_launcher = lr; 0522 //lr->setParamDict(paramDict()); 0523 lr->setTool(this); 0524 0525 connect(lr, SIGNAL(message(int,QString)), this, SLOT(sendMessage(int,QString))); 0526 connect(lr, SIGNAL(output(QString)), this, SLOT(filterOutput(QString))); 0527 connect(lr, SIGNAL(done(int)), this, SLOT(finish(int))); 0528 } 0529 0530 bool Base::installLauncher() 0531 { 0532 if (m_launcher) { 0533 return true; 0534 } 0535 0536 QString type = readEntry("type"); 0537 KILE_DEBUG_MAIN << "installing launcher of type " << type; 0538 Launcher *lr = Q_NULLPTR; 0539 0540 if ( type == "Process" ) { 0541 lr = new ProcessLauncher(); 0542 } 0543 else if ( type == "Konsole" ) { 0544 lr = new KonsoleLauncher(); 0545 } 0546 else if ( type == "DocumentViewer" ) { 0547 lr = new DocumentViewerLauncher(); 0548 } 0549 0550 if (lr) { 0551 installLauncher(lr); 0552 return true; 0553 } 0554 else { 0555 m_launcher = Q_NULLPTR; 0556 return false; 0557 } 0558 } 0559 0560 void Base::setupAsChildTool(KileTool::Base *child) 0561 { 0562 Q_UNUSED(child); 0563 } 0564 0565 void Base::sendMessage(int type, const QString &msg) 0566 { 0567 emit(message(type, msg, name())); 0568 } 0569 0570 void Base::filterOutput(const QString & str) 0571 { 0572 //here you have the change to filter the output and do some error extraction for example 0573 //this should be done by a OutputFilter class 0574 0575 //idea: store the buffer until a complete line (or more) has been received then parse these lines 0576 //just send the buf immediately to the output widget, the results of the parsing are displayed in 0577 //the log widget anyway. 0578 emit(output(str)); 0579 } 0580 0581 bool Base::addDict(const QString & key, const QString & value) 0582 { 0583 bool e = !(paramDict().contains(key)); 0584 paramDict()[key] = value; 0585 return e; 0586 } 0587 0588 bool Base::needsUpdate(const QString &target, const QString &source) 0589 { 0590 KILE_DEBUG_MAIN << "==Base::needsUpdate(" << target << "," << source; 0591 QFileInfo targetinfo(target); 0592 QFileInfo sourceinfo(source); 0593 QDateTime currDateTime = QDateTime::currentDateTime(); 0594 0595 if(!(sourceinfo.exists() && sourceinfo.isReadable())) { 0596 KILE_DEBUG_MAIN << "\treturning false: source does not exist"; 0597 return false; 0598 } 0599 0600 if(!targetinfo.exists()) { 0601 KILE_DEBUG_MAIN << "\treturning true: target does not exist"; 0602 return true; 0603 } 0604 0605 KILE_DEBUG_MAIN << "\ttarget: " << targetinfo.lastModified().toString(); 0606 KILE_DEBUG_MAIN << "\tsource: " << sourceinfo.lastModified().toString(); 0607 0608 if(targetinfo.lastModified() > currDateTime) { 0609 KILE_DEBUG_MAIN << "targetinfo.lastModifiedTime() is in the future"; 0610 return false; 0611 } 0612 else if(sourceinfo.lastModified() > currDateTime) { 0613 KILE_DEBUG_MAIN << "sourceinfo.lastModifiedTime() is in the future"; 0614 return false; 0615 } 0616 0617 KILE_DEBUG_MAIN << "\treturning " << (targetinfo.lastModified() < sourceinfo.lastModified()); 0618 return targetinfo.lastModified() < sourceinfo.lastModified(); 0619 } 0620 0621 Compile::Compile(const QString &name, Manager * manager, bool prepare /*= true*/) 0622 : Base(name, manager, prepare) 0623 { 0624 setFlags( flags() | NeedTargetDirExec | NeedTargetDirWrite); 0625 } 0626 0627 Compile::~Compile() 0628 {} 0629 0630 bool Compile::checkSource() 0631 { 0632 if ( !Base::checkSource() ) return false; 0633 0634 bool isRoot = true; 0635 KileDocument::TextInfo *docinfo = manager()->info()->docManager()->textInfoFor(source()); 0636 if (docinfo) { 0637 isRoot = (readEntry("checkForRoot") == "yes") ? docinfo->isLaTeXRoot() : true; 0638 } 0639 0640 if (!isRoot) 0641 { 0642 return manager()->queryContinue(i18n("The document %1 is not a LaTeX root document; continue anyway?", source()), i18n("Continue?")); 0643 } 0644 0645 return true; 0646 } 0647 0648 View::View(const QString &name, Manager * manager, bool prepare /*= true*/) 0649 : Base(name, manager, prepare) 0650 { 0651 setFlags(NeedTargetDirExec | NeedTargetExists | NeedTargetRead); 0652 0653 KILE_DEBUG_MAIN << "View: flag " << (flags() & NeedTargetExists); 0654 setMsg(NeedTargetExists, ki18n("The file %1/%2 does not exist; did you compile the source file?")); 0655 } 0656 0657 View::~View() 0658 { 0659 } 0660 0661 0662 Archive::Archive(const QString &name, Manager * manager, bool prepare /* = true*/) 0663 : Base(name, manager,prepare) 0664 { 0665 setFlags( NeedTargetDirExec | NeedTargetDirWrite ); 0666 } 0667 0668 Archive::~Archive() 0669 {} 0670 0671 bool Archive::checkPrereqs() 0672 { 0673 if(!m_project) { 0674 sendMessage(Error,i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to archive, then choose Archive again.")); 0675 return false; 0676 } 0677 else if(m_fileList.isEmpty()) { 0678 sendMessage(Error, i18n("No files have been chosen for archiving.")); 0679 return false; 0680 } 0681 else { 0682 return true; 0683 } 0684 } 0685 0686 void Archive::setSource(const QString &source, const QString& workingDir) 0687 { 0688 Q_UNUSED(workingDir); 0689 QUrl url = QUrl::fromLocalFile(source); 0690 m_project = manager()->info()->docManager()->projectFor(url); 0691 if ( !m_project ) 0692 m_project = manager()->info()->docManager()->activeProject(); 0693 if ( !m_project ) 0694 m_project = manager()->info()->docManager()->selectProject(i18n("Archive Project")); 0695 if ( !m_project ) 0696 { 0697 Base::setSource(source); 0698 return; 0699 } 0700 0701 manager()->info()->docManager()->projectSave(m_project); 0702 Base::setSource(m_project->url().toLocalFile()); 0703 m_fileList = m_project->archiveFileList(); 0704 0705 addDict("%AFL", m_fileList); 0706 0707 KILE_DEBUG_MAIN << "===KileTool::Archive::setSource("<< source << ")=============="; 0708 KILE_DEBUG_MAIN << "m_fileList="<<m_fileList<< Qt::endl; 0709 } 0710 0711 Convert::Convert(const QString &name, Manager * manager, bool prepare /*= true*/) 0712 : Base(name, manager,prepare) 0713 { 0714 setFlags( flags() | NeedTargetDirExec | NeedTargetDirWrite ); 0715 } 0716 0717 Convert::~Convert() 0718 { 0719 } 0720 0721 bool Convert::determineSource() 0722 { 0723 bool br = Base::determineSource(); 0724 setSource(baseDir() + '/' + S() + '.' + from()); 0725 return br; 0726 } 0727 0728 Sequence::Sequence(const QString &name, Manager *manager, bool prepare /*= true*/) 0729 : Base(name, manager, prepare), m_latexOutputHandler(Q_NULLPTR) 0730 { 0731 } 0732 0733 Sequence::~Sequence() { 0734 qDeleteAll(m_tools); 0735 } 0736 0737 LaTeXOutputHandler* Sequence::latexOutputHandler() 0738 { 0739 return m_latexOutputHandler; 0740 } 0741 0742 void Sequence::setLaTeXOutputHandler(LaTeXOutputHandler *h) 0743 { 0744 m_latexOutputHandler = h; 0745 } 0746 0747 bool Sequence::determineSource() 0748 { 0749 QString src = source(); 0750 0751 // check whether the source has been set already 0752 if(!src.isEmpty()) { 0753 return true; 0754 } 0755 0756 // the basedir is determined from the current compile target, 0757 // determined by getCompileName() 0758 LaTeXOutputHandler *h = Q_NULLPTR; 0759 src = m_ki->getCompileName(false, &h); 0760 0761 setSource(src); 0762 setLaTeXOutputHandler(h); 0763 0764 return true; 0765 } 0766 0767 bool Sequence::requestSaveAll() 0768 { 0769 // if one of the tools in the sequence requests save-all, then we also 0770 // request it 0771 for(Base *tool : m_tools) { 0772 if(tool->requestSaveAll()) { 0773 return true; 0774 } 0775 } 0776 0777 return false; 0778 } 0779 0780 void Sequence::setupSequenceTools() 0781 { 0782 QStringList toolNameList = readEntry("sequence").split(','); 0783 QString tl, cfg; 0784 for(QStringList::iterator i = toolNameList.begin(); i != toolNameList.end(); ++i) { 0785 QString fullToolSpec = (*i).trimmed(); 0786 extract(fullToolSpec, tl, cfg); 0787 0788 Base *tool = manager()->createTool(tl, cfg, false); // create tool with delayed preparation 0789 if (tool) { 0790 KILE_DEBUG_MAIN << "===tool created with name " << tool->name(); 0791 if(!(manager()->info()->watchFile() && tool->isViewer())) { // FIXME: why this? 0792 KILE_DEBUG_MAIN << "\tqueueing " << tl << "(" << cfg << ") with " << source(); 0793 m_tools.push_back(tool); 0794 } 0795 else { 0796 delete tool; 0797 } 0798 } 0799 else { 0800 m_unknownToolSpec = fullToolSpec; 0801 qDeleteAll(m_tools); 0802 m_tools.clear(); 0803 return; 0804 } 0805 } 0806 } 0807 0808 int Sequence::run() 0809 { 0810 KILE_DEBUG_MAIN << "==KileTool::Sequence::run()=================="; 0811 0812 determineSource(); 0813 if (!checkSource()) { 0814 // tools in 'm_tools' will be deleted in the destructor 0815 return NoValidSource; 0816 } 0817 0818 if(!m_unknownToolSpec.isEmpty()) { 0819 // 'm_tools' is empty 0820 sendMessage(Error, i18n("Unknown tool %1.", m_unknownToolSpec)); 0821 emit(done(this, Failed, m_childToolSpawned)); 0822 return ConfigureFailed; 0823 } 0824 0825 for(Base *tool : m_tools) { 0826 tool->setSource(source()); 0827 0828 // if we are running a 'LaTeX' tool here, we still have to set the 0829 // appropriate LaTeXOutputHandler 0830 { 0831 LaTeX *latex = dynamic_cast<LaTeX*>(tool); 0832 if(latex && m_latexOutputHandler) { 0833 latex->setLaTeXOutputHandler(m_latexOutputHandler); 0834 } 0835 } 0836 0837 manager()->run(tool); 0838 } 0839 0840 m_tools.clear(); // the tools will be deleted by the tool manager from now on 0841 emit(done(this, Silent, m_childToolSpawned)); 0842 0843 return Success; 0844 } 0845 } 0846