~ubuntu-branches/ubuntu/hardy/codeblocks/hardy-backports

« back to all changes in this revision

Viewing changes to src/sdk/toolsmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 
4
 *
 
5
 * $Revision: 4909 $
 
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 $
 
8
 */
 
9
 
 
10
#include "sdk_precomp.h"
 
11
 
 
12
#ifndef CB_PRECOMP
 
13
    #include <wx/intl.h>
 
14
    #include <wx/process.h>
 
15
    #include <wx/menu.h>
 
16
    #include <wx/msgdlg.h>
 
17
    #include "toolsmanager.h"
 
18
    #include "manager.h"
 
19
    #include "macrosmanager.h"
 
20
    #include "configmanager.h"
 
21
    #include "logmanager.h"
 
22
    #include "configmanager.h"
 
23
    #include "pipedprocess.h"
 
24
    #include "globals.h"
 
25
    #include "sdk_events.h"
 
26
#endif
 
27
 
 
28
#include <wx/mdi.h>
 
29
#include <wx/listimpl.cpp>
 
30
#include "configuretoolsdlg.h"
 
31
 
 
32
template<> ToolsManager* Mgr<ToolsManager>::instance = 0;
 
33
template<> bool  Mgr<ToolsManager>::isShutdown = false;
 
34
 
 
35
WX_DEFINE_LIST(ToolsList);
 
36
 
 
37
const int idToolsConfigure = wxNewId();
 
38
const int idToolProcess = wxNewId();
 
39
 
 
40
BEGIN_EVENT_TABLE(ToolsManager, wxEvtHandler)
 
41
    EVT_MENU(idToolsConfigure, ToolsManager::OnConfigure)
 
42
 
 
43
    EVT_IDLE(ToolsManager::OnIdle)
 
44
 
 
45
    EVT_PIPEDPROCESS_STDOUT(idToolProcess, ToolsManager::OnToolStdOutput)
 
46
    EVT_PIPEDPROCESS_STDERR(idToolProcess, ToolsManager::OnToolErrOutput)
 
47
    EVT_PIPEDPROCESS_TERMINATED(idToolProcess, ToolsManager::OnToolTerminated)
 
48
END_EVENT_TABLE()
 
49
 
 
50
ToolsManager::ToolsManager()
 
51
    : m_Menu(0L),
 
52
    m_pProcess(0L),
 
53
    m_Pid(0)
 
54
{
 
55
    LoadTools();
 
56
    Manager::Get()->GetAppWindow()->PushEventHandler(this);
 
57
}
 
58
 
 
59
ToolsManager::~ToolsManager()
 
60
{
 
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);
 
64
 
 
65
    m_ItemsManager.Clear();
 
66
 
 
67
    // free-up any memory used for tools
 
68
    m_Tools.DeleteContents(true);
 
69
    m_Tools.Clear();
 
70
}
 
71
 
 
72
void ToolsManager::CreateMenu(wxMenuBar* menuBar)
 
73
{
 
74
}
 
75
 
 
76
void ToolsManager::ReleaseMenu(wxMenuBar* menuBar)
 
77
{
 
78
}
 
79
 
 
80
bool ToolsManager::Execute(const cbTool* tool)
 
81
{
 
82
    if (m_pProcess)
 
83
    {
 
84
        cbMessageBox(_("Another tool is currently executing.\n"
 
85
                        "Please allow for it to finish before launching another tool..."),
 
86
                        _("Error"), wxICON_ERROR);
 
87
        return false;
 
88
    }
 
89
 
 
90
    if (!tool)
 
91
        return false;
 
92
 
 
93
    wxString cmdline;
 
94
    wxString cmd = tool->GetCommand();
 
95
    wxString params = tool->GetParams();
 
96
    wxString dir = tool->GetWorkingDir();
 
97
 
 
98
    // hack to force-update macros
 
99
    Manager::Get()->GetMacrosManager()->RecalcVars(0, 0, 0);
 
100
 
 
101
    Manager::Get()->GetMacrosManager()->ReplaceMacros(cmd);
 
102
    Manager::Get()->GetMacrosManager()->ReplaceMacros(params);
 
103
    Manager::Get()->GetMacrosManager()->ReplaceMacros(dir);
 
104
 
 
105
    if (tool->GetLaunchOption() == cbTool::LAUNCH_NEW_CONSOLE_WINDOW)
 
106
    {
 
107
#ifndef __WXMSW__
 
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"
 
113
#else
 
114
        #define CONSOLE_RUNNER "cb_console_runner.exe"
 
115
#endif
 
116
        wxString baseDir = ConfigManager::GetExecutableFolder();
 
117
        if (wxFileExists(baseDir + wxT("/" CONSOLE_RUNNER)))
 
118
            cmdline << baseDir << wxT("/" CONSOLE_RUNNER " ");
 
119
    }
 
120
 
 
121
    if (!cmdline.Replace(_T("$SCRIPT"), cmd << _T(" ") << params))
 
122
        // if they didn't specify $SCRIPT, append:
 
123
        cmdline << cmd;
 
124
 
 
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);
 
129
 
 
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()));
 
133
 
 
134
    bool pipe = true;
 
135
    int flags = wxEXEC_ASYNC;
 
136
 
 
137
    switch (tool->GetLaunchOption())
 
138
    {
 
139
        case cbTool::LAUNCH_NEW_CONSOLE_WINDOW:
 
140
            pipe = false; // no need to pipe output channels...
 
141
            break;
 
142
 
 
143
        case cbTool::LAUNCH_HIDDEN:
 
144
            break; // use the default values of pipe and flags...
 
145
 
 
146
        case cbTool::LAUNCH_VISIBLE:
 
147
        case cbTool::LAUNCH_VISIBLE_DETACHED:
 
148
            flags |= wxEXEC_NOHIDE;
 
149
            pipe = false;
 
150
            break;
 
151
    }
 
152
 
 
153
    if (tool->GetLaunchOption() == cbTool::LAUNCH_VISIBLE_DETACHED)
 
154
    {
 
155
        int pid = wxExecute(cmdline, flags);
 
156
 
 
157
        if (!pid)
 
158
        {
 
159
            cbMessageBox(_("Couldn't execute tool. Check the log for details."), _("Error"), wxICON_ERROR);
 
160
            return false;
 
161
        }
 
162
        else
 
163
        {
 
164
            CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, LogManager::app_log);
 
165
            Manager::Get()->ProcessEvent(evtSwitch);        // switch to default log
 
166
         }
 
167
    }
 
168
    else
 
169
    {
 
170
        m_pProcess = new PipedProcess((void**)&m_pProcess, this, idToolProcess, pipe, dir);
 
171
        m_Pid = wxExecute(cmdline, flags, m_pProcess);
 
172
 
 
173
        if (!m_Pid)
 
174
        {
 
175
            cbMessageBox(_("Couldn't execute tool. Check the log for details."), _("Error"), wxICON_ERROR);
 
176
            delete m_pProcess;
 
177
            m_pProcess = 0;
 
178
            m_Pid = 0;
 
179
            return false;
 
180
        }
 
181
        else
 
182
        {
 
183
            CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, LogManager::app_log);
 
184
            Manager::Get()->ProcessEvent(evtSwitch);        // switch to default log
 
185
        }
 
186
    }
 
187
 
 
188
    return true;
 
189
} // end of Execute
 
190
 
 
191
void ToolsManager::AddTool(const cbTool* tool, bool save)
 
192
{
 
193
    if (tool)
 
194
    {
 
195
        InsertTool(m_Tools.GetCount(), tool, save);
 
196
    }
 
197
} // end of AddTool
 
198
 
 
199
void ToolsManager::InsertTool(int position, const cbTool* tool, bool save)
 
200
{
 
201
    m_Tools.Insert(position, new cbTool(*tool));
 
202
    if (save)
 
203
    {
 
204
        SaveTools();
 
205
    }
 
206
} // end of InsertTool
 
207
 
 
208
void ToolsManager::RemoveToolByIndex(int index)
 
209
{
 
210
    int idx = 0;
 
211
    for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
 
212
    {
 
213
        if (idx == index)
 
214
        {
 
215
            DoRemoveTool(node);
 
216
            return;
 
217
        }
 
218
        ++idx;
 
219
    }
 
220
}
 
221
 
 
222
void ToolsManager::DoRemoveTool(ToolsList::Node* node)
 
223
{
 
224
    if (node)
 
225
    {
 
226
        m_Tools.DeleteNode(node);
 
227
        SaveTools();
 
228
    }
 
229
}
 
230
 
 
231
cbTool* ToolsManager::GetToolByMenuId(int id)
 
232
{
 
233
    for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
 
234
    {
 
235
        cbTool* tool = node->GetData();
 
236
        if (tool->GetMenuId() == id)
 
237
            return tool;
 
238
    }
 
239
    return 0L;
 
240
}
 
241
 
 
242
cbTool* ToolsManager::GetToolByIndex(int index)
 
243
{
 
244
    int idx = 0;
 
245
    for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
 
246
    {
 
247
        cbTool* tool = node->GetData();
 
248
        if (idx == index)
 
249
            return tool;
 
250
        ++idx;
 
251
    }
 
252
    return 0L;
 
253
}
 
254
 
 
255
void ToolsManager::LoadTools()
 
256
{
 
257
    ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("tools"));
 
258
    wxArrayString list = cfg->EnumerateSubPaths(_("/"));
 
259
    for (unsigned int i = 0; i < list.GetCount(); ++i)
 
260
    {
 
261
        cbTool tool;
 
262
        tool.SetName( cfg->Read(_T("/") + list[i] + _T("/name")));
 
263
        if (tool.GetName().IsEmpty())
 
264
            continue;
 
265
        tool.SetCommand(cfg->Read(_T("/") + list[i] + _T("/command")));
 
266
        if (tool.GetCommand().IsEmpty())
 
267
            continue;
 
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"))));
 
271
 
 
272
        AddTool(&tool, false);
 
273
    }
 
274
    Manager::Get()->GetLogManager()->Log(_("Configured %d tools"), m_Tools.GetCount());
 
275
}
 
276
 
 
277
void ToolsManager::SaveTools()
 
278
{
 
279
    ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("tools"));
 
280
    wxArrayString list = cfg->EnumerateSubPaths(_("/"));
 
281
    for (unsigned int i = 0; i < list.GetCount(); ++i)
 
282
    {
 
283
        cfg->DeleteSubPath(list[i]);
 
284
    }
 
285
 
 
286
    int count = 0;
 
287
    for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
 
288
    {
 
289
        cbTool* tool = node->GetData();
 
290
        wxString elem;
 
291
 
 
292
        // prepend a 0-padded 2-digit number to keep ordering
 
293
        wxString tmp;
 
294
        tmp.Printf(_T("tool%2.2d"), count++);
 
295
 
 
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()));
 
302
    }
 
303
}
 
304
 
 
305
void ToolsManager::BuildToolsMenu(wxMenu* menu)
 
306
{
 
307
    // clear previously added menu items
 
308
    m_ItemsManager.Clear();
 
309
 
 
310
    // add menu items for tools
 
311
    m_Menu = menu;
 
312
    if (m_Menu->GetMenuItemCount() > 0)
 
313
    {
 
314
        m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
 
315
    }
 
316
 
 
317
    for (ToolsList::Node* node = m_Tools.GetFirst(); node; node = node->GetNext())
 
318
    {
 
319
        cbTool* tool = node->GetData();
 
320
        if (tool->GetName() == CB_TOOLS_SEPARATOR)
 
321
        {
 
322
            m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
 
323
            continue;
 
324
        }
 
325
        if (tool->GetMenuId() == -1)
 
326
        {
 
327
            tool->SetMenuId(wxNewId());
 
328
        }
 
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);
 
333
    }
 
334
 
 
335
    if (m_Tools.GetCount() > 0)
 
336
    {
 
337
        m_ItemsManager.Add(menu, wxID_SEPARATOR, _T(""), _T(""));
 
338
    }
 
339
    m_ItemsManager.Add(menu, idToolsConfigure, _("&Configure tools..."), _("Add/remove user-defined tools"));
 
340
}
 
341
 
 
342
int ToolsManager::Configure()
 
343
{
 
344
    CodeBlocksEvent event(cbEVT_MENUBAR_CREATE_BEGIN);
 
345
    Manager::Get()->ProcessEvent(event);
 
346
 
 
347
    ConfigureToolsDlg dlg(Manager::Get()->GetAppWindow());
 
348
    PlaceWindow(&dlg);
 
349
    dlg.ShowModal();
 
350
    SaveTools();
 
351
    BuildToolsMenu(m_Menu);
 
352
 
 
353
    CodeBlocksEvent event2(cbEVT_MENUBAR_CREATE_END);
 
354
    Manager::Get()->ProcessEvent(event2);
 
355
 
 
356
    return 0;
 
357
} // end of Configure
 
358
 
 
359
// events
 
360
 
 
361
void ToolsManager::OnConfigure(wxCommandEvent& event)
 
362
{
 
363
    Configure();
 
364
}
 
365
 
 
366
void ToolsManager::OnToolClick(wxCommandEvent& event)
 
367
{
 
368
    cbTool* tool = GetToolByMenuId(event.GetId());
 
369
    if (!Execute(tool))
 
370
        cbMessageBox(_("Could not execute ") + tool->GetName());
 
371
}
 
372
 
 
373
void ToolsManager::OnIdle(wxIdleEvent& event)
 
374
{
 
375
    if (m_pProcess)
 
376
    {
 
377
        if (m_pProcess->HasInput())
 
378
        {
 
379
            event.RequestMore();
 
380
        }
 
381
    }
 
382
    else
 
383
        event.Skip();
 
384
}
 
385
 
 
386
void ToolsManager::OnToolStdOutput(CodeBlocksEvent& event)
 
387
{
 
388
    Manager::Get()->GetLogManager()->Log(_T("stdout> ") + event.GetString());
 
389
}
 
390
 
 
391
void ToolsManager::OnToolErrOutput(CodeBlocksEvent& event)
 
392
{
 
393
    Manager::Get()->GetLogManager()->Log(_T("stderr> ") + event.GetString());
 
394
}
 
395
 
 
396
void ToolsManager::OnToolTerminated(CodeBlocksEvent& event)
 
397
{
 
398
    m_Pid = 0;
 
399
    m_pProcess = 0;
 
400
 
 
401
    Manager::Get()->GetLogManager()->Log(F(_T("Tool execution terminated with status %d"), event.GetInt()));
 
402
}