You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kile/src/kile/kiletoolmanager.cpp

512 lines
13 KiB

/***************************************************************************
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 <stdlib.h> //for getenv()
#include <tqstring.h>
#include <tqfileinfo.h>
#include <tqwidgetstack.h>
#include <tqtimer.h>
#include <tqregexp.h>
#include <tqthread.h>
#include <kaction.h>
#include <ktextedit.h>
#include <kconfig.h>
#include "kiledebug.h"
#include <klocale.h>
#include <tdeparts/partmanager.h>
#include <kmessagebox.h>
#include <kapplication.h>
#include <ksimpleconfig.h>
#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, KAction *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<TDEConfig*>(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<TDEConfig*>(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"