2
* This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3
* http://www.gnu.org/licenses/lgpl-3.0.html
6
* $Id: toolsmanager.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
7
* $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/sdk/toolsmanager.cpp $
10
#include "sdk_precomp.h"
14
#include <wx/process.h>
16
#include <wx/msgdlg.h>
17
#include "toolsmanager.h"
19
#include "macrosmanager.h"
20
#include "configmanager.h"
21
#include "logmanager.h"
22
#include "configmanager.h"
23
#include "pipedprocess.h"
25
#include "sdk_events.h"
29
#include <wx/listimpl.cpp>
30
#include "configuretoolsdlg.h"
32
template<> ToolsManager* Mgr<ToolsManager>::instance = 0;
33
template<> bool Mgr<ToolsManager>::isShutdown = false;
35
WX_DEFINE_LIST(ToolsList);
37
const int idToolsConfigure = wxNewId();
38
const int idToolProcess = wxNewId();
40
BEGIN_EVENT_TABLE(ToolsManager, wxEvtHandler)
41
EVT_MENU(idToolsConfigure, ToolsManager::OnConfigure)
43
EVT_IDLE(ToolsManager::OnIdle)
45
EVT_PIPEDPROCESS_STDOUT(idToolProcess, ToolsManager::OnToolStdOutput)
46
EVT_PIPEDPROCESS_STDERR(idToolProcess, ToolsManager::OnToolErrOutput)
47
EVT_PIPEDPROCESS_TERMINATED(idToolProcess, ToolsManager::OnToolTerminated)
50
ToolsManager::ToolsManager()
56
Manager::Get()->GetAppWindow()->PushEventHandler(this);
59
ToolsManager::~ToolsManager()
61
// this is a core manager, so it is removed when the app is shutting down.
62
// in this case, the app has already un-hooked us, so no need to do it ourselves...
63
// Manager::Get()->GetAppWindow()->RemoveEventHandler(this);
65
m_ItemsManager.Clear();
67
// free-up any memory used for tools
68
m_Tools.DeleteContents(true);
72
void ToolsManager::CreateMenu(wxMenuBar* menuBar)
76
void ToolsManager::ReleaseMenu(wxMenuBar* menuBar)
80
bool ToolsManager::Execute(const cbTool* tool)
84
cbMessageBox(_("Another tool is currently executing.\n"
85
"Please allow for it to finish before launching another tool..."),
86
_("Error"), wxICON_ERROR);
94
wxString cmd = tool->GetCommand();
95
wxString params = tool->GetParams();
96
wxString dir = tool->GetWorkingDir();
98
// hack to force-update macros
99
Manager::Get()->GetMacrosManager()->RecalcVars(0, 0, 0);
101
Manager::Get()->GetMacrosManager()->ReplaceMacros(cmd);
102
Manager::Get()->GetMacrosManager()->ReplaceMacros(params);
103
Manager::Get()->GetMacrosManager()->ReplaceMacros(dir);
105
if (tool->GetLaunchOption() == cbTool::LAUNCH_NEW_CONSOLE_WINDOW)
108
// for non-win platforms, use m_ConsoleTerm to run the console app
109
wxString term = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/console_terminal"), DEFAULT_CONSOLE_TERM);
110
term.Replace(_T("$TITLE"), _T("'") + tool->GetName() + _T("'"));
111
cmdline << term << _T(" ");
112
#define CONSOLE_RUNNER "cb_console_runner"
114
#define CONSOLE_RUNNER "cb_console_runner.exe"
116
wxString baseDir = ConfigManager::GetExecutableFolder();
117
if (wxFileExists(baseDir + wxT("/" CONSOLE_RUNNER)))
118
cmdline << baseDir << wxT("/" CONSOLE_RUNNER " ");
121
if (!cmdline.Replace(_T("$SCRIPT"), cmd << _T(" ") << params))
122
// if they didn't specify $SCRIPT, append:
125
if(!(Manager::Get()->GetMacrosManager()))
126
return false; // We cannot afford the Macros Manager to fail here!
127
// What if it failed already?
128
wxSetWorkingDirectory(dir);
130
// log info so user can troubleshoot
131
dir = wxGetCwd(); // read in the actual working dir
132
Manager::Get()->GetLogManager()->Log(F(_("Launching tool '%s': %s (in %s)"), tool->GetName().c_str(), cmdline.c_str(), dir.c_str()));
135
int flags = wxEXEC_ASYNC;
137
switch (tool->GetLaunchOption())
139
case cbTool::LAUNCH_NEW_CONSOLE_WINDOW:
140
pipe = false; // no need to pipe output channels...
143
case cbTool::LAUNCH_HIDDEN:
144
break; // use the default values of pipe and flags...
146
case cbTool::LAUNCH_VISIBLE:
147
case cbTool::LAUNCH_VISIBLE_DETACHED:
148
flags |= wxEXEC_NOHIDE;
153
if (tool->GetLaunchOption() == cbTool::LAUNCH_VISIBLE_DETACHED)
155
int pid = wxExecute(cmdline, flags);
159
cbMessageBox(_("Couldn't execute tool. Check the log for details."), _("Error"), wxICON_ERROR);
164
CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, LogManager::app_log);
165
Manager::Get()->ProcessEvent(evtSwitch); // switch to default log
170
m_pProcess = new PipedProcess((void**)&m_pProcess, this, idToolProcess, pipe, dir);
171
m_Pid = wxExecute(cmdline, flags, m_pProcess);
175
cbMessageBox(_("Couldn't execute tool. Check the log for details."), _("Error"), wxICON_ERROR);
183
CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, LogManager::app_log);
184
Manager::Get()->ProcessEvent(evtSwitch); // switch to default log
191
void ToolsManager::AddTool(const cbTool* tool, bool save)
195
InsertTool(m_Tools.GetCount(), tool, save);
199
void ToolsManager::InsertTool(int position, const cbTool* tool, bool save)
201
m_Tools.Insert(position, new cbTool(*tool));
206
} // end of InsertTool
208
void ToolsManager::RemoveToolByIndex(int index)
211
for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
222
void ToolsManager::DoRemoveTool(ToolsList::Node* node)
226
m_Tools.DeleteNode(node);
231
cbTool* ToolsManager::GetToolByMenuId(int id)
233
for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
235
cbTool* tool = node->GetData();
236
if (tool->GetMenuId() == id)
242
cbTool* ToolsManager::GetToolByIndex(int index)
245
for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
247
cbTool* tool = node->GetData();
255
void ToolsManager::LoadTools()
257
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("tools"));
258
wxArrayString list = cfg->EnumerateSubPaths(_("/"));
259
for (unsigned int i = 0; i < list.GetCount(); ++i)
262
tool.SetName( cfg->Read(_T("/") + list[i] + _T("/name")));
263
if (tool.GetName().IsEmpty())
265
tool.SetCommand(cfg->Read(_T("/") + list[i] + _T("/command")));
266
if (tool.GetCommand().IsEmpty())
268
tool.SetParams(cfg->Read(_T("/") + list[i] + _T("/params")));
269
tool.SetWorkingDir(cfg->Read(_T("/") + list[i] + _T("/workingDir")));
270
tool.SetLaunchOption(static_cast<cbTool::eLaunchOption>(cfg->ReadInt(_T("/") + list[i] + _T("/launchOption"))));
272
AddTool(&tool, false);
274
Manager::Get()->GetLogManager()->Log(_("Configured %d tools"), m_Tools.GetCount());
277
void ToolsManager::SaveTools()
279
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("tools"));
280
wxArrayString list = cfg->EnumerateSubPaths(_("/"));
281
for (unsigned int i = 0; i < list.GetCount(); ++i)
283
cfg->DeleteSubPath(list[i]);
287
for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
289
cbTool* tool = node->GetData();
292
// prepend a 0-padded 2-digit number to keep ordering
294
tmp.Printf(_T("tool%2.2d"), count++);
296
elem << _T("/") << tmp << _T("/");
297
cfg->Write(elem + _T("name"), tool->GetName());
298
cfg->Write(elem + _T("command"), tool->GetCommand());
299
cfg->Write(elem + _T("params"), tool->GetParams());
300
cfg->Write(elem + _T("workingDir"), tool->GetWorkingDir());
301
cfg->Write(elem + _T("launchOption"), static_cast<int>(tool->GetLaunchOption()));
305
void ToolsManager::BuildToolsMenu(wxMenu* menu)
307
// clear previously added menu items
308
m_ItemsManager.Clear();
310
// add menu items for tools
312
if (m_Menu->GetMenuItemCount() > 0)
314
m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
317
for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
319
cbTool* tool = node->GetData();
320
if (tool->GetName() == CB_TOOLS_SEPARATOR)
322
m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
325
if (tool->GetMenuId() == -1)
327
tool->SetMenuId(wxNewId());
329
m_ItemsManager.Add(menu, tool->GetMenuId(), tool->GetName(), tool->GetName());
330
Connect(tool->GetMenuId(), -1, wxEVT_COMMAND_MENU_SELECTED,
331
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
332
&ToolsManager::OnToolClick);
335
if (m_Tools.GetCount() > 0)
337
m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
339
m_ItemsManager.Add(menu, idToolsConfigure, _("&Configure tools..."), _("Add/remove user-defined tools"));
342
int ToolsManager::Configure()
344
CodeBlocksEvent event(cbEVT_MENUBAR_CREATE_BEGIN);
345
Manager::Get()->ProcessEvent(event);
347
ConfigureToolsDlg dlg(Manager::Get()->GetAppWindow());
351
BuildToolsMenu(m_Menu);
353
CodeBlocksEvent event2(cbEVT_MENUBAR_CREATE_END);
354
Manager::Get()->ProcessEvent(event2);
357
} // end of Configure
361
void ToolsManager::OnConfigure(wxCommandEvent& event)
366
void ToolsManager::OnToolClick(wxCommandEvent& event)
368
cbTool* tool = GetToolByMenuId(event.GetId());
370
cbMessageBox(_("Could not execute ") + tool->GetName());
373
void ToolsManager::OnIdle(wxIdleEvent& event)
377
if (m_pProcess->HasInput())
386
void ToolsManager::OnToolStdOutput(CodeBlocksEvent& event)
388
Manager::Get()->GetLogManager()->Log(_T("stdout> ") + event.GetString());
391
void ToolsManager::OnToolErrOutput(CodeBlocksEvent& event)
393
Manager::Get()->GetLogManager()->Log(_T("stderr> ") + event.GetString());
396
void ToolsManager::OnToolTerminated(CodeBlocksEvent& event)
401
Manager::Get()->GetLogManager()->Log(F(_T("Tool execution terminated with status %d"), event.GetInt()));