11
11
#include <sdk.h> // Code::Blocks SDK
13
// Required extra includes
13
// Required extra includes
16
#include "ThreadSearch.h"
16
17
#include "ThreadSearchLoggerTree.h"
17
18
#include "ThreadSearchEvent.h"
18
#include "ThreadSearchView.h"
19
#include "ThreadSearchView.h"
20
#include "ThreadSearchControlIds.h"
20
22
ThreadSearchLoggerTree::ThreadSearchLoggerTree(ThreadSearchView& threadSearchView,
21
ThreadSearch& threadSearchPlugin,
22
InsertIndexManager::eFileSorting fileSorting,
25
: ThreadSearchLoggerBase(threadSearchView, threadSearchPlugin, fileSorting)
27
, m_FirstItemProcessed(false)
23
ThreadSearch& threadSearchPlugin,
24
InsertIndexManager::eFileSorting fileSorting,
27
: ThreadSearchLoggerBase(threadSearchView, threadSearchPlugin, fileSorting)
29
, m_FirstItemProcessed(false)
29
31
m_pTreeLog = new wxTreeCtrl(pParent, id, wxDefaultPosition, wxSize(1,1), wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_FULL_ROW_HIGHLIGHT|wxTR_HIDE_ROOT|wxTR_DEFAULT_STYLE|wxSUNKEN_BORDER);
30
32
m_pTreeLog->SetMinSize(wxSize(100, 100));
31
m_pTreeLog->AddRoot(wxEmptyString);
33
m_FilesParentId = m_pTreeLog->AddRoot(wxEmptyString);
33
// Events are managed dynamically to be able to stop/start management when required.
34
ConnectEvents(pParent);
35
// Events are managed dynamically to be able to stop/start management when required.
36
ConnectEvents(pParent);
38
40
ThreadSearchLoggerTree::~ThreadSearchLoggerTree()
40
wxWindow* pParent = m_pTreeLog->GetParent();
41
if ( pParent != NULL )
43
// Events are managed dynamically to be able to stop/start management when required.
44
DisconnectEvents(pParent);
46
m_pTreeLog->Destroy();
42
wxWindow* pParent = m_pTreeLog->GetParent();
43
if ( pParent != NULL )
45
// Events are managed dynamically to be able to stop/start management when required.
46
DisconnectEvents(pParent);
48
m_pTreeLog->Destroy();
51
53
wxWindow* ThreadSearchLoggerTree::GetWindow()
57
59
void ThreadSearchLoggerTree::SetFocus()
59
m_pTreeLog->SetFocus();
61
m_pTreeLog->SetFocus();
63
65
void ThreadSearchLoggerTree::ConnectEvents(wxEvtHandler* pEvtHandler)
65
// Dynamic event connections.
66
int id = m_pTreeLog->GetId();
67
pEvtHandler->Connect(id, wxEVT_COMMAND_TREE_SEL_CHANGED,
68
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
69
&ThreadSearchLoggerTree::OnLoggerTreeClick, NULL, this);
71
pEvtHandler->Connect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
72
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
73
&ThreadSearchLoggerTree::OnLoggerTreeDoubleClick, NULL, this);
67
// Dynamic event connections.
68
int id = m_pTreeLog->GetId();
69
pEvtHandler->Connect(id, wxEVT_COMMAND_TREE_SEL_CHANGED,
70
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
71
&ThreadSearchLoggerTree::OnLoggerTreeClick, NULL, this);
73
pEvtHandler->Connect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
74
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
75
&ThreadSearchLoggerTree::OnLoggerTreeDoubleClick, NULL, this);
78
pEvtHandler->Connect(id, wxEVT_COMMAND_TREE_ITEM_MENU,
79
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
80
&ThreadSearchLoggerTree::OnLoggerTreeContextualMenu, NULL, this);
82
pEvtHandler->Connect(idMenuCtxDeleteItem, wxEVT_COMMAND_MENU_SELECTED,
83
wxCommandEventHandler(ThreadSearchLoggerTree::OnDeleteTreeItem), NULL, this);
85
pEvtHandler->Connect(idMenuCtxDeleteAllItems, wxEVT_COMMAND_MENU_SELECTED,
86
wxCommandEventHandler(ThreadSearchLoggerTree::OnDeleteAllTreeItems), NULL, this);
77
91
void ThreadSearchLoggerTree::DisconnectEvents(wxEvtHandler* pEvtHandler)
79
// Dynamic event disconnections.
80
int id = m_pTreeLog->GetId();
81
pEvtHandler->Disconnect(id, wxEVT_COMMAND_TREE_SEL_CHANGED,
82
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
83
&ThreadSearchLoggerTree::OnLoggerTreeClick, NULL, this);
85
pEvtHandler->Disconnect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
86
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
87
&ThreadSearchLoggerTree::OnLoggerTreeDoubleClick, NULL, this);
93
// Dynamic event disconnections.
94
int id = m_pTreeLog->GetId();
95
pEvtHandler->Disconnect(id, wxEVT_COMMAND_TREE_SEL_CHANGED,
96
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
97
&ThreadSearchLoggerTree::OnLoggerTreeClick, NULL, this);
99
pEvtHandler->Disconnect(id, wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
100
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
101
&ThreadSearchLoggerTree::OnLoggerTreeDoubleClick, NULL, this);
104
pEvtHandler->Disconnect(id, wxEVT_COMMAND_TREE_ITEM_MENU,
105
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)
106
&ThreadSearchLoggerTree::OnLoggerTreeContextualMenu, NULL, this);
108
pEvtHandler->Disconnect(idMenuCtxDeleteItem, wxEVT_COMMAND_MENU_SELECTED,
109
wxCommandEventHandler(ThreadSearchLoggerTree::OnDeleteTreeItem), NULL, this);
111
pEvtHandler->Disconnect(idMenuCtxDeleteAllItems, wxEVT_COMMAND_MENU_SELECTED,
112
wxCommandEventHandler(ThreadSearchLoggerTree::OnDeleteAllTreeItems), NULL, this);
113
#endif // wxUSE_MENUS
91
117
void ThreadSearchLoggerTree::OnLoggerTreeClick(wxTreeEvent& event)
93
// Manages list log left double click
94
// Gets file path and line from list control
95
wxString filepath(wxEmptyString);
97
if ( GetFileLineFromTreeEvent(event, filepath, line) == false )
119
// Manages list log left single click
120
wxTreeItemId itemId = event.GetItem();
121
if ( itemId.IsOk() && hasResultLineForTreeItem(itemId) )
99
cbMessageBox(wxT("Failed to retrieve file path and line number"), wxT("Error"), wxICON_ERROR);
123
// Gets file path and line from list control
124
wxString filepath(wxEmptyString);
126
if ( GetFileLineFromTreeEvent(event, filepath, line) == false )
128
cbMessageBox(_("Failed to retrieve file path and line number"), _("Error"), wxICON_ERROR);
131
m_ThreadSearchView.OnLoggerClick(filepath, line);
102
m_ThreadSearchView.OnLoggerClick(filepath, line);
107
137
void ThreadSearchLoggerTree::OnLoggerTreeDoubleClick(wxTreeEvent& event)
109
// Manages list log left double click
110
// Gets file path and line from list control
111
wxString filepath(wxEmptyString);
113
if ( GetFileLineFromTreeEvent(event, filepath, line) == false )
139
// Manages list log left double click
140
wxTreeItemId itemId = event.GetItem();
141
if ( itemId.IsOk() && hasResultLineForTreeItem(itemId) )
115
cbMessageBox(wxT("Failed to retrieve file path and line number"), wxT("Error"), wxICON_ERROR);
143
// Gets file path and line from list control
144
wxString filepath(wxEmptyString);
146
if ( GetFileLineFromTreeEvent(event, filepath, line) == false )
148
cbMessageBox(_("Failed to retrieve file path and line number"), _("Error"), wxICON_ERROR);
151
m_ThreadSearchView.OnLoggerDoubleClick(filepath, line);
118
m_ThreadSearchView.OnLoggerDoubleClick(filepath, line);
158
void ThreadSearchLoggerTree::OnLoggerTreeContextualMenu(wxTreeEvent& event)
160
wxPoint clientPoint = event.GetPoint();
161
m_ToDeleteItemId = event.GetItem();
162
ShowMenu(clientPoint);
163
// No event skipping, otherwise, Message notebook contextual menu pops up
167
bool ThreadSearchLoggerTree::hasResultLineForTreeItem(wxTreeItemId treeItemId)
169
return (m_pTreeLog->GetItemText(treeItemId).StartsWith(_("=>")) == false) || (m_pTreeLog->ItemHasChildren(treeItemId));
124
173
bool ThreadSearchLoggerTree::GetFileLineFromTreeEvent(wxTreeEvent& event, wxString& filepath, long &line)
126
wxTreeItemId lineItemId;
127
wxTreeItemId fileItemId;
128
wxTreeItemId rootItemId = m_pTreeLog->GetRootItem();
129
wxTreeItemId eventItemId = event.GetItem();
132
filepath = wxEmptyString;
137
// We test if we are on a file item or a line item.
138
// As root is hidden, we have only file and line items on tree.
139
if ( m_pTreeLog->GetItemParent(eventItemId) == rootItemId )
141
fileItemId = eventItemId;
142
wxTreeItemIdValue cookie;
143
lineItemId = m_pTreeLog->GetFirstChild(eventItemId, cookie);
144
if ( lineItemId.IsOk() == false )
149
lineItemId = eventItemId;
150
fileItemId = m_pTreeLog->GetItemParent(lineItemId);
153
// We extract line and file path values
154
// Look at ThreadSearchLoggerTree::OnThreadSearchEvent to have format
157
const wxString& lineText = m_pTreeLog->GetItemText(lineItemId);
158
int columnPos = lineText.Find(':');
159
if ( columnPos == wxNOT_FOUND )
162
if ( lineText.Left(columnPos).ToLong(&line) == false )
166
const wxString& fileText = m_pTreeLog->GetItemText(fileItemId);
167
int fileLength = fileText.Find(wxT(" ("));
168
if ( fileLength == wxNOT_FOUND )
171
int dirBegin = fileLength + 2; // 2 for " ("
172
int dirLength = fileText.Length() - dirBegin - 1;
173
if ( dirLength <= 0 )
176
wxFileName filename(fileText.Mid(dirBegin, dirLength), fileText.Left(fileLength));
177
filepath = filename.GetFullPath();
175
wxTreeItemId lineItemId;
176
wxTreeItemId fileItemId;
177
wxTreeItemId tmpItemId;
178
wxTreeItemId eventItemId = event.GetItem();
181
filepath = wxEmptyString;
186
// Looks for deepest child, which is the first interesting item (line item)
187
wxTreeItemIdValue cookie;
188
tmpItemId = eventItemId;
190
lineItemId = tmpItemId;
191
tmpItemId = m_pTreeLog->GetFirstChild(lineItemId, cookie);
192
} while ( tmpItemId.IsOk() == true );
193
fileItemId = m_pTreeLog->GetItemParent(lineItemId);
195
// We extract line and file path values
196
// Look at ThreadSearchLoggerTree::OnThreadSearchEvent to have format
199
const wxString& lineText = m_pTreeLog->GetItemText(lineItemId);
200
int columnPos = lineText.Find(':');
201
if ( columnPos == wxNOT_FOUND )
204
if ( lineText.Left(columnPos).ToLong(&line) == false )
208
const wxString& fileText = m_pTreeLog->GetItemText(fileItemId);
209
int fileLength = fileText.Find(wxT(" ("));
210
if ( fileLength == wxNOT_FOUND )
213
int dirBegin = fileLength + 2; // 2 for " ("
214
int dirLength = fileText.Length() - dirBegin - 1;
215
if ( dirLength <= 0 )
218
wxFileName filename(fileText.Mid(dirBegin, dirLength), fileText.Left(fileLength));
219
filepath = filename.GetFullPath();
186
228
void ThreadSearchLoggerTree::OnThreadSearchEvent(const ThreadSearchEvent& event)
188
// A search event has been sent by the worker thread.
190
const wxArrayString& words = event.GetLineTextArray();
191
const wxFileName& filename(event.GetString());
192
bool setFocus(false);
193
wxTreeItemId rootItemId(m_pTreeLog->GetRootItem());
194
wxTreeItemId fileItemId;
195
long index = m_IndexManager.GetInsertionIndex(filename.GetFullPath());
196
long nb_items = m_pTreeLog->GetChildrenCount(rootItemId, false);
198
wxASSERT(index != wxNOT_FOUND);
199
wxASSERT((words.GetCount() % 2) == 0);
201
// Use of Freeze Thaw to enhance speed and limit blink effect
202
m_pTreeLog->Freeze();
203
wxTreeItemId lineItemId;
205
if ( index == nb_items )
207
fileItemId = m_pTreeLog->AppendItem(rootItemId,
208
wxString::Format(wxT("%s (%s)"),
209
filename.GetFullName().c_str(),
210
filename.GetPath().c_str()));
214
fileItemId = m_pTreeLog->InsertItem(rootItemId, index,
215
wxString::Format(wxT("%s (%s)"),
216
filename.GetFullName().c_str(),
217
filename.GetPath().c_str()));
220
for (size_t i = 0; i < words.GetCount(); i += 2)
222
lineItemId = m_pTreeLog->AppendItem(fileItemId, wxString::Format(wxT("%s: %s"),
223
words[i].c_str(), // Line index starting from 1
224
words[i+1].c_str())); // File line matching search expression
226
// We update preview log for first list item
227
if ( (m_FirstItemProcessed == false) &&
228
(m_pTreeLog->GetChildrenCount(fileItemId, false) == 1) &&
229
(m_pTreeLog->GetChildrenCount(rootItemId, false) == 1) )
231
// Expand first file item
232
m_pTreeLog->Expand(fileItemId);
234
// Select first item (generates selection event to update ThreadSearchView code preview)
235
m_pTreeLog->SelectItem(lineItemId);
237
// to avoid lots of preview that freezes app
238
m_FirstItemProcessed = true;
240
// It is useful to give focus to tree to navigate in results
241
// just after running a search
247
if ( setFocus == true )
249
// On Linux, executing SetFocus just after SelectItem
250
// does not work. Probbly because of Thaw...
251
m_pTreeLog->SetFocus();
230
// A search event has been sent by the worker thread.
232
const wxArrayString& words = event.GetLineTextArray();
233
const wxFileName& filename(event.GetString());
234
bool setFocus(false);
235
wxTreeItemId fileItemId;
236
long index = m_IndexManager.GetInsertionIndex(filename.GetFullPath());
237
long nb_items = m_pTreeLog->GetChildrenCount(m_FilesParentId, false);
239
wxASSERT(index != wxNOT_FOUND);
240
wxASSERT((words.GetCount() % 2) == 0);
242
// Use of Freeze Thaw to enhance speed and limit blink effect
243
m_pTreeLog->Freeze();
244
wxTreeItemId lineItemId;
246
if ( index == nb_items )
248
fileItemId = m_pTreeLog->AppendItem(m_FilesParentId,
249
wxString::Format(wxT("%s (%s)"),
250
filename.GetFullName().c_str(),
251
filename.GetPath().c_str()));
255
fileItemId = m_pTreeLog->InsertItem(m_FilesParentId, index,
256
wxString::Format(wxT("%s (%s)"),
257
filename.GetFullName().c_str(),
258
filename.GetPath().c_str()));
261
for (size_t i = 0; i < words.GetCount(); i += 2)
263
lineItemId = m_pTreeLog->AppendItem(fileItemId, wxString::Format(wxT("%s: %s"),
264
words[i].c_str(), // Line index starting from 1
265
words[i+1].c_str())); // File line matching search expression
267
// We update preview log for first list item
268
if ( (m_FirstItemProcessed == false) &&
269
(m_pTreeLog->GetChildrenCount(fileItemId, false) == 1) &&
270
(m_pTreeLog->GetChildrenCount(m_FilesParentId, false) == 1) )
272
// Expand first file item
273
m_pTreeLog->Expand(fileItemId);
275
// Select first item (generates selection event to update ThreadSearchView code preview)
276
m_pTreeLog->SelectItem(lineItemId);
278
// to avoid lots of preview that freezes app
279
m_FirstItemProcessed = true;
281
// It is useful to give focus to tree to navigate in results
282
// just after running a search
288
if ( setFocus == true )
290
// On Linux, executing SetFocus just after SelectItem
291
// does not work. Probbly because of Thaw...
292
m_pTreeLog->SetFocus();
256
297
void ThreadSearchLoggerTree::Clear()
258
// As wxTreeCtrl::DeleteChildren sends lots of selected events
259
// and because we don't want any wxTreeCtrl event to be processed
260
// during delete, we disable events management during tree cleaning
261
// (DisconnectEvents then ConnectEvents).
262
wxWindow* pParent = m_pTreeLog->GetParent();
263
if ( pParent == NULL ) return;
299
// As wxTreeCtrl::DeleteChildren sends lots of selected events
300
// and because we don't want any wxTreeCtrl event to be processed
301
// during delete, we disable events management during tree cleaning
302
// (DisconnectEvents then ConnectEvents).
303
wxWindow* pParent = m_pTreeLog->GetParent();
304
if ( pParent == NULL ) return;
265
DisconnectEvents(pParent);
306
DisconnectEvents(pParent);
267
308
m_pTreeLog->DeleteChildren(m_pTreeLog->GetRootItem());
268
309
m_FirstItemProcessed = false;