Skip to content

Commit

Permalink
Implemented: Feature Request: external tool: multi instances
Browse files Browse the repository at this point in the history
    fixes: eranif#1016
  • Loading branch information
eranif committed Nov 14, 2015
1 parent ba582db commit 9150e10
Show file tree
Hide file tree
Showing 25 changed files with 1,607 additions and 384 deletions.
4 changes: 4 additions & 0 deletions ExternalTools/ExternalTools.project
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
<File Name="externaltoolsdata.cpp"/>
<File Name="externaltoolsdata.h"/>
<File Name="CMakeLists.txt"/>
<File Name="ExternalToolsProcessManager.h"/>
<File Name="ExternalToolsProcessManager.cpp"/>
</VirtualDirectory>
<Dependencies/>
<VirtualDirectory Name="UI">
Expand All @@ -41,6 +43,8 @@
<File Name="externaltooldlg.h"/>
<File Name="../formbuilder/external_tools.wxcp"/>
<File Name="../formbuilder/NewToolBase.wxcp"/>
<File Name="ExternalToolsManager.h"/>
<File Name="ExternalToolsManager.cpp"/>
</VirtualDirectory>
<Dependencies Name="DebugUnicode"/>
<Dependencies Name="ReleaseUnicode"/>
Expand Down
66 changes: 66 additions & 0 deletions ExternalTools/ExternalToolsManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "ExternalToolsManager.h"
#include <algorithm>
#include "ExternalToolsProcessManager.h"
#include "globals.h"
#include "bitmap_loader.h"
#include "imanager.h"

ExternalToolsManager::ExternalToolsManager(wxWindow* parent)
: ExternalToolsManagerBase(parent)
{
DoPopulateTable();
}

ExternalToolsManager::~ExternalToolsManager() {}

void ExternalToolsManager::OnKill(wxCommandEvent& event)
{
wxDataViewItemArray arr;
m_dvListCtrlTasks->GetSelections(arr);
for(size_t i = 0; i < arr.size(); ++i) {
wxDataViewItem item = arr.Item(i);
ExternalToolItemData* cd = (ExternalToolItemData*)m_dvListCtrlTasks->GetItemData(item);
ToolsTaskManager::Instance()->Stop(cd->m_pid);
}
DoPopulateTable();
}

void ExternalToolsManager::OnKillAll(wxCommandEvent& event)
{
ToolsTaskManager::Instance()->StopAll();
DoPopulateTable();
}

void ExternalToolsManager::OnKillAllUI(wxUpdateUIEvent& event) { event.Enable(m_dvListCtrlTasks->GetItemCount()); }
void ExternalToolsManager::OnKillUI(wxUpdateUIEvent& event)
{
event.Enable(m_dvListCtrlTasks->GetSelectedItemsCount());
}

void ExternalToolsManager::DoPopulateTable()
{
DoClear();
BitmapLoader* b = clGetManager()->GetStdIcons();
const ExternalToolItemData::Map_t& tools = ToolsTaskManager::Instance()->GetTools();
std::for_each(tools.begin(), tools.end(), [&](const std::pair<int, ExternalToolItemData>& p) {
wxVector<wxVariant> cols;
cols.push_back(::MakeIconText(wxString() << p.first, b->LoadBitmap("cog")));
cols.push_back(p.second.m_command);
m_dvListCtrlTasks->AppendItem(cols, (wxUIntPtr)p.second.Clone());
});
}

void ExternalToolsManager::DoClear()
{
for(int i = 0; i < m_dvListCtrlTasks->GetItemCount(); ++i) {
ExternalToolItemData* cd =
(ExternalToolItemData*)m_dvListCtrlTasks->GetItemData(m_dvListCtrlTasks->RowToItem(i));
delete cd;
}
m_dvListCtrlTasks->DeleteAllItems();
}
void ExternalToolsManager::OnRefresh(wxCommandEvent& event)
{
wxUnusedVar(event);
DoPopulateTable();
}
22 changes: 22 additions & 0 deletions ExternalTools/ExternalToolsManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef EXTERNALTOOLSMANAGER_H
#define EXTERNALTOOLSMANAGER_H
#include "external_tools.h"

class ExternalToolsManager : public ExternalToolsManagerBase
{
public:
ExternalToolsManager(wxWindow* parent);
virtual ~ExternalToolsManager();

protected:
virtual void OnRefresh(wxCommandEvent& event);
void DoPopulateTable();
void DoClear();

protected:
virtual void OnKill(wxCommandEvent& event);
virtual void OnKillAll(wxCommandEvent& event);
virtual void OnKillAllUI(wxUpdateUIEvent& event);
virtual void OnKillUI(wxUpdateUIEvent& event);
};
#endif // EXTERNALTOOLSMANAGER_H
152 changes: 152 additions & 0 deletions ExternalTools/ExternalToolsProcessManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#include "ExternalToolsProcessManager.h"
#include "event_notifier.h"
#include "globals.h"
#include "imanager.h"
#include "asyncprocess.h"
#include "macromanager.h"
#include "environmentconfig.h"
#include "processreaderthread.h"
#include <algorithm>
#include <wx/utils.h>
#include <wx/process.h>
#include <wx/msgdlg.h>

/**
* @class MyProcess
* @brief handler class for capturing non-redirected processes termination
*/
class MyProcess : public wxProcess
{
public:
MyProcess() {}
virtual ~MyProcess() {}
void OnTerminate(int pid, int status)
{
ToolsTaskManager::Instance()->ProcessTerminated(pid);
delete this;
}
};

ToolsTaskManager* ToolsTaskManager::ms_instance = 0;

ToolsTaskManager::ToolsTaskManager()
{
Bind(wxEVT_ASYNC_PROCESS_OUTPUT, &ToolsTaskManager::OnProcessOutput, this);
Bind(wxEVT_ASYNC_PROCESS_TERMINATED, &ToolsTaskManager::OnProcessEnd, this);
}

ToolsTaskManager::~ToolsTaskManager()
{
Unbind(wxEVT_ASYNC_PROCESS_OUTPUT, &ToolsTaskManager::OnProcessOutput, this);
Unbind(wxEVT_ASYNC_PROCESS_TERMINATED, &ToolsTaskManager::OnProcessEnd, this);
}

ToolsTaskManager* ToolsTaskManager::Instance()
{
if(ms_instance == 0) {
ms_instance = new ToolsTaskManager();
}
return ms_instance;
}

void ToolsTaskManager::Release()
{
if(ms_instance) {
delete ms_instance;
}
ms_instance = 0;
}

void ToolsTaskManager::OnProcessEnd(clProcessEvent& event)
{
clGetManager()->AppendOutputTabText(kOutputTab_Output, event.GetOutput());
clGetManager()->AppendOutputTabText(kOutputTab_Output, "\n");

// delete the process
IProcess* proc = event.GetProcess();
ProcessTerminated(proc->GetPid());
delete proc;

// Notify codelite to test for any modified bufferes
EventNotifier::Get()->PostReloadExternallyModifiedEvent();
}

void ToolsTaskManager::OnProcessOutput(clProcessEvent& event)
{
clGetManager()->AppendOutputTabText(kOutputTab_Output, event.GetOutput());
}

void ToolsTaskManager::StartTool(const ToolInfo& ti)
{
wxString command, working_dir;
command << ti.GetPath();
::WrapWithQuotes(command);

command << " " << ti.GetArguments();
working_dir = ti.GetWd();

command = MacroManager::Instance()->Expand(
command,
clGetManager(),
(clGetManager()->GetWorkspace() ? clGetManager()->GetWorkspace()->GetActiveProjectName() : ""));
working_dir = MacroManager::Instance()->Expand(
working_dir,
clGetManager(),
(clGetManager()->GetWorkspace() ? clGetManager()->GetWorkspace()->GetActiveProjectName() : ""));

wxString projectName;
wxString configName;
if(clCxxWorkspaceST::Get()->IsOpen()) {
projectName = clCxxWorkspaceST::Get()->GetActiveProjectName();
BuildConfigPtr bldConf = clCxxWorkspaceST::Get()->GetProjBuildConf(projectName, wxEmptyString);
if(bldConf) {
configName = bldConf->GetName();
}
}

EnvSetter envGuard(clGetManager()->GetEnv(), NULL, projectName, configName);
//::WrapInShell(command);

int pid = wxNOT_FOUND;
if(ti.GetCaptureOutput()) {
IProcess* proc = ::CreateAsyncProcess(this, command, IProcessCreateConsole, working_dir);
if(!proc) {
::wxMessageBox(_("Failed to launch tool\n'") + command + "'",
"CodeLite",
wxICON_ERROR | wxOK | wxCENTER,
EventNotifier::Get()->TopFrame());
return;
}

pid = proc->GetPid();

} else {
pid = ::wxExecute(command, wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER, new MyProcess());
}

if(pid > 0) {
ExternalToolItemData item(command, pid);
m_tools.insert(std::make_pair(pid, item));
}
}

void ToolsTaskManager::ProcessTerminated(int pid)
{
if(m_tools.find(pid) != m_tools.end()) {
m_tools.erase(pid);
}
}

void ToolsTaskManager::StopAll()
{
std::for_each(m_tools.begin(), m_tools.end(), [&](const std::pair<int, ExternalToolItemData> &p) {
::wxKill(p.second.m_pid, wxSIGKILL, NULL, wxKILL_CHILDREN);
});
}

void ToolsTaskManager::Stop(int pid)
{
if(m_tools.find(pid) != m_tools.end()) {
::wxKill(pid, wxSIGKILL, NULL, wxKILL_CHILDREN);
}
}
62 changes: 62 additions & 0 deletions ExternalTools/ExternalToolsProcessManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef EXTERNALTOOLSPROCESSMANAGER_H
#define EXTERNALTOOLSPROCESSMANAGER_H

#include <wx/event.h>
#include "cl_command_event.h"
#include "externaltoolsdata.h"
#include <vector>

struct ExternalToolItemData {
wxString m_command;
int m_pid;

ExternalToolItemData(const wxString& command, int pid)
: m_command(command)
, m_pid(pid)
{
}

ExternalToolItemData* Clone() const { return new ExternalToolItemData(m_command, m_pid); }
~ExternalToolItemData() {}
typedef std::map<int, ExternalToolItemData> Map_t;
};

class ToolsTaskManager : public wxEvtHandler
{
static ToolsTaskManager* ms_instance;

protected:
ExternalToolItemData::Map_t m_tools;

protected:
void OnProcessEnd(clProcessEvent& event);
void OnProcessOutput(clProcessEvent& event);

public:
static ToolsTaskManager* Instance();
static void Release();
/**
* @brief launch a tool
*/
void StartTool(const ToolInfo& ti);
/**
* @brief a tool process terminated, remove it from our internal tracking table
*/
void ProcessTerminated(int pid);
/**
* @brief stop all processes
*/
void StopAll();
/**
* @brief stop a single tool
*/
void Stop(int pid);

const ExternalToolItemData::Map_t& GetTools() const { return m_tools; }

private:
ToolsTaskManager();
virtual ~ToolsTaskManager();
};

#endif // EXTERNALTOOLSPROCESSMANAGER_H
2 changes: 2 additions & 0 deletions ExternalTools/NewToolBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class NewToolBase : public wxDialog
wxTextCtrl* m_textCtrlIcon16;
wxButton* m_buttonBrowseIcon16;
wxCheckBox* m_checkBoxSaveAllFilesBefore;
wxCheckBox* m_checkBoxCaptureOutput;
wxStdDialogButtonSizer* m_stdBtnSizer2;
wxButton* m_button4;
wxButton* m_button6;
Expand Down Expand Up @@ -85,6 +86,7 @@ class NewToolBase : public wxDialog
wxTextCtrl* GetTextCtrlIcon16() { return m_textCtrlIcon16; }
wxButton* GetButtonBrowseIcon16() { return m_buttonBrowseIcon16; }
wxCheckBox* GetCheckBoxSaveAllFilesBefore() { return m_checkBoxSaveAllFilesBefore; }
wxCheckBox* GetCheckBoxCaptureOutput() { return m_checkBoxCaptureOutput; }
NewToolBase(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("External Tool"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize(-1,-1), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
virtual ~NewToolBase();
};
Expand Down
2 changes: 1 addition & 1 deletion ExternalTools/NewToolBase_formbuilder_bitmaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static unsigned char xml_res_file_0[] = {
60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,
110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,63,62,10,60,114,101,
115,111,117,114,99,101,32,120,109,108,110,115,61,34,104,116,116,112,58,
47,47,119,119,119,46,119,120,119,105,110,100,111,119,115,46,111,114,103,
47,47,119,119,119,46,119,120,119,105,100,103,101,116,115,46,111,114,103,
47,119,120,120,114,99,34,47,62,10};

void wxC3E45InitBitmapResources()
Expand Down
Loading

0 comments on commit 9150e10

Please sign in to comment.