/*************************************************************************** begin : Tue Nov 25 2003 copyright : (C) 2003 by Jeroen Wijnhout email : Jeroen.Wijnhout@kdemail.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kiletoolmanager.h" #include //for getenv() #include #include #include #include #include #include #include #include #include #include "kiledebug.h" #include #include #include #include #include #include "kileinfo.h" #include "kileconfig.h" #include "kileproject.h" #include "kiletool_enums.h" #include "kilestdtools.h" #include "kilelogwidget.h" #include "kileoutputwidget.h" #include "kiledocmanager.h" #include "kilesidebar.h" namespace KileTool { QueueItem::QueueItem(Base *tool, const TQString & cfg, bool block) : m_tool(tool), m_cfg(cfg), m_bBlock(block) { } QueueItem::~QueueItem() { delete m_tool; } Base* Queue::tool() const { if ( head() ) return head()->tool(); else return 0; } const TQString Queue::cfg() const { if ( head() ) return head()->cfg(); else return TQString(); } bool Queue::shouldBlock() const { if ( head() ) return head()->shouldBlock(); else return false; } void Queue::enqueueNext(QueueItem *item) { if ( count() < 2 ) enqueue(item); else { QueueItem *headitem = dequeue(); Queue *oldqueue = new Queue(*this); setAutoDelete(false); clear(); KILE_DEBUG() << "\tenqueueing: " << headitem->tool()->name() << endl; enqueue(headitem); KILE_DEBUG() << "\tenqueueing: " << item->tool()->name() << endl; enqueue(item); while ( oldqueue->head() ) { KILE_DEBUG() << "\tenqueueing: " << oldqueue->head()->tool()->name() << endl; enqueue(oldqueue->dequeue()); } } } Manager::Manager(KileInfo *ki, TDEConfig *config, KileWidget::LogMsg *log, KileWidget::Output *output, KParts::PartManager *manager, TQWidgetStack *stack, TDEAction *stop, uint to) : m_ki(ki), m_config(config), m_log(log), m_output(output), m_pm(manager), m_stack(stack), m_stop(stop), m_bClear(true), m_nLastResult(Success), m_nTimeout(to) { m_timer = new TQTimer(this); connect(m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(enableClear())); connect(stop, TQT_SIGNAL(activated()), this, TQT_SLOT(stop())); } Manager::~Manager() {} bool Manager::shouldBlock() { return m_queue.shouldBlock(); } void Manager::enableClear() { m_bClear = true; } bool Manager::queryContinue(const TQString & question, const TQString & caption /*= TQString()*/) { return (KMessageBox::warningContinueCancel(m_stack, question, caption, KStdGuiItem::cont(), "showNotALaTeXRootDocumentWarning") == KMessageBox::Continue); } int Manager::run(const TQString &tool, const TQString & cfg, bool insertNext /*= false*/, bool block /*= false*/) { if (!m_factory) { m_log->printMsg(Error, i18n("No factory installed, contact the author of Kile.")); return ConfigureFailed; } Base* pTool = m_factory->create(tool); if (!pTool) { m_log->printMsg(Error, i18n("Unknown tool %1.").arg(tool)); return ConfigureFailed; } return run(pTool, cfg, insertNext, block); } int Manager::run(Base *tool, const TQString & cfg, bool insertNext /*= false*/, bool block /*= false*/) { KILE_DEBUG() << "==KileTool::Manager::run(Base *)============" << endl; if (m_bClear && (m_queue.count() == 0) ) { m_log->clear(); m_ki->setLogPresent(false); m_output->clear(); } if ( tool->needsToBePrepared() ) tool->prepareToRun(cfg); else tool->configure(cfg); //FIXME: shouldn't restart timer if a Sequence command takes longer than the 10 secs //restart timer, so we only clear the logs if a tool is started after 10 sec. m_bClear=false; m_timer->start(m_nTimeout); if ( insertNext ) m_queue.enqueueNext(new QueueItem(tool, cfg, block)); else m_queue.enqueue(new QueueItem(tool, cfg, block)); KILE_DEBUG() << "\tin queue: " << m_queue.count() << endl; if ( m_queue.count() == 1 ) return runNextInQueue(); else if ( m_queue.count() > 1 ) return Running; else return ConfigureFailed; } int Manager::runNext(const TQString &tool , const TQString &config, bool block /*= false*/) { return run(tool, config, true, block); } int Manager::runNext(Base *tool, const TQString &config, bool block /*= false*/) { return run(tool, config, true, block); } int Manager::runBlocking(const TQString &tool, const TQString &config /*= TQString()*/, bool insertAtTop /*= false*/) { if ( run(tool, config, insertAtTop, true) == Running ) return lastResult(); else return Failed; } int Manager::runNextBlocking(const TQString &tool, const TQString &config) { return runBlocking(tool, config, true); } int Manager::runNextInQueue() { Base *head = m_queue.tool(); if (head) { if (m_log->lines() > 1) m_log->append("\n"); if ( ! head->isPrepared() ) head->prepareToRun(); int status; if ( (status=head->run()) != Running ) //tool did not even start, clear queue { stop(); m_queue.setAutoDelete(true); m_queue.clear(); m_queue.setAutoDelete(false); return status; } emit(toolStarted()); return Running; } return ConfigureFailed; } void Manager::initTool(Base *tool) { tool->setInfo(m_ki); tool->setConfig(m_config); connect(tool, TQT_SIGNAL(message(int, const TQString &, const TQString &)), m_log, TQT_SLOT(printMsg(int, const TQString &, const TQString &))); connect(tool, TQT_SIGNAL(output(const TQString &)), m_output, TQT_SLOT(receive(const TQString &))); connect(tool, TQT_SIGNAL(done(Base*,int)), this, TQT_SLOT(done(Base*, int))); connect(tool, TQT_SIGNAL(start(Base* )), this, TQT_SLOT(started(Base*))); connect(tool, TQT_SIGNAL(requestSaveAll(bool, bool)), this, TQT_SIGNAL(requestSaveAll(bool, bool))); } void Manager::started(Base *tool) { KILE_DEBUG() << "STARTING tool: " << tool->name() << endl; m_stop->setEnabled(true); if (tool->isViewer()) { if ( tool == m_queue.tool() ) m_queue.dequeue(); m_stop->setEnabled(false); TQTimer::singleShot(100, this, TQT_SLOT(runNextInQueue())); } } void Manager::stop() { m_stop->setEnabled(false); if ( m_queue.tool() ) m_queue.tool()->stop(); } void Manager::done(Base *tool, int result) { m_stop->setEnabled(false); m_nLastResult = result; if ( tool != m_queue.tool() ) //oops, tool finished async, could happen with view tools { delete tool; return; } delete m_queue.dequeue(); if ( result == Aborted) tool->sendMessage(Error, i18n("Aborted")); if ( result != Success && result != Silent ) //abort execution, delete all remaining tools { m_queue.setAutoDelete(true); m_queue.clear(); m_queue.setAutoDelete(false); m_ki->outputView()->showPage(m_log); } else //continue runNextInQueue(); } TQString Manager::currentGroup(const TQString &name, bool usequeue, bool useproject) { if (useproject) { KileProject *project = m_ki->docManager()->activeProject(); if (project) { TQString cfg = configName(name, dynamic_cast(project->config())); if ( cfg.length() > 0 ) return groupFor(name, cfg); } } if (usequeue && m_queue.tool() && (m_queue.tool()->name() == name) && (!m_queue.cfg().isNull()) ) return groupFor(name, m_queue.cfg()); else return groupFor(name, m_config); } bool Manager::retrieveEntryMap(const TQString & name, Config & map, bool usequeue, bool useproject, const TQString & cfg /*= TQString()*/) { TQString group = (cfg == TQString() ) ? currentGroup(name, usequeue, useproject) : groupFor(name, cfg); KILE_DEBUG() << "==KileTool::Manager::retrieveEntryMap=============" << endl; KILE_DEBUG() << "\t" << name << " => " << group << endl; if ( m_config->hasGroup(group) ) { map = m_config->entryMap(group); //use project overrides KileProject *project = m_ki->docManager()->activeProject(); if ( useproject && project) { TDEConfig *prjcfg = dynamic_cast(project->config()); if ( prjcfg ) { TQString grp = groupFor(name, prjcfg); Config prjmap = prjcfg->entryMap(grp); for (Config::Iterator it = prjmap.begin(); it != prjmap.end(); ++it) { map[it.key()] = it.data(); } } } } else return false; return true; } void Manager::saveEntryMap(const TQString & name, Config & map, bool usequeue, bool useproject) { KILE_DEBUG() << "==KileTool::Manager::saveEntryMap=============" << endl; TQString group = currentGroup(name, usequeue, useproject); KILE_DEBUG() << "\t" << name << " => " << group << endl; m_config->setGroup(group); Config::Iterator it; for ( it = map.begin() ; it != map.end(); ++it) { if ( ! it.data().isEmpty() ) m_config->writeEntry(it.key(), it.data()); } } bool Manager::configure(Base *tool, const TQString & cfg /*=TQString()*/) { KILE_DEBUG() << "==KileTool::Manager::configure()===============" << endl; //configure the tool Config map; if ( ! retrieveEntryMap(tool->name(), map, true, true, cfg) ) { m_log->printMsg(Error, i18n("Cannot find the tool %1 in the configuration database.").arg(tool->name())); return false; } tool->setEntryMap(map); return true; } void Manager::wantGUIState(const TQString & state) { KILE_DEBUG() << "REQUESTED state: " << state << endl; emit(requestGUIState(state)); } TQStringList toolList(TDEConfig *config, bool menuOnly) { KILE_DEBUG() << "==KileTool::toolList()==================" << endl; TQStringList groups = config->groupList(), tools; TQRegExp re = TQRegExp("Tool/(.+)/.+"); for ( uint i = 0; i < groups.count(); ++i ) { if ( re.exactMatch(groups[i]) ) { if ( ! groups[i].endsWith(configName(re.cap(1), config)) ) continue; if ( (! menuOnly) || ( menuFor(re.cap(1),config) != "none" ) ) { tools.append(re.cap(1)); } } } tools.sort(); return tools; } TQString configName(const TQString & tool, TDEConfig *config) { config->setGroup("Tools"); return config->readEntry(tool, ""); } void setConfigName(const TQString & tool, const TQString & name, TDEConfig *config) { KILE_DEBUG() << "==KileTool::Manager::setConfigName(" << tool << "," << name << ")===============" << endl; config->setGroup("Tools"); config->writeEntry(tool, name); } TQString groupFor(const TQString &tool, TDEConfig *config) { return groupFor(tool, configName(tool, config)); } TQString groupFor(const TQString & tool, const TQString & cfg /* = Default */ ) { return "Tool/" + tool + '/' + cfg; } void extract(const TQString &str, TQString &tool, TQString &cfg) { static TQRegExp re("([^\\(]*)\\((.*)\\)"); TQString lcl = str; lcl.stripWhiteSpace(); cfg = TQString(); if ( re.exactMatch(lcl) ) { tool = re.cap(1).stripWhiteSpace(); cfg = re.cap(2).stripWhiteSpace(); } else tool = lcl; KILE_DEBUG() << "===void extract(const TQString &str = " << str << " , TQString &tool = " << tool << ", TQString &cfg = " << cfg << " )===" << endl; } TQString format(const TQString & tool, const TQString &cfg) { if (!cfg.isNull()) return tool + '(' + cfg + ')'; else return tool; } TQStringList configNames(const TQString &tool, TDEConfig *config) { TQStringList groups = config->groupList(), configs; TQRegExp re = TQRegExp("Tool/"+ tool +"/(.+)"); for ( uint i = 0; i < groups.count(); ++i ) { if ( re.exactMatch(groups[i]) ) { configs.append(re.cap(1)); } } return configs; } TQString menuFor(const TQString &tool, TDEConfig *config) { config->setGroup("ToolsGUI"); return config->readEntry(tool, "Other,gear").section(',',0,0); } TQString iconFor(const TQString &tool, TDEConfig *config) { config->setGroup("ToolsGUI"); return config->readEntry(tool, "Other,gear").section(',',1,1); } void setGUIOptions(const TQString &tool, const TQString &menu, const TQString &icon, TDEConfig *config) { TQString entry = menu + ',' + icon; config->setGroup("ToolsGUI"); config->writeEntry(tool, entry); } TQString categoryFor(const TQString &clss) { if ( clss == "Compile" || clss == "LaTeX" ) return "Compile"; if ( clss == "Convert" ) return "Convert"; if ( clss == "View" || clss == "ViewBib" || clss == "ViewHTML" || clss == "ForwardDVI" ) return "View"; if ( clss == "Sequence" ) return "Sequence"; if ( clss == "Archive") return "Archive"; return "Base"; } } #include "kiletoolmanager.moc"