Unbind working
[public/netxms.git] / src / client / console / plugins / AlarmBrowser / view.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Portable management console - Alarm Browser plugin
4 ** Copyright (C) 2007 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: view.cpp
21 **
22 **/
23
24 #include "alarm_browser.h"
25
26
27 //
28 // Event table
29 //
30
31 BEGIN_EVENT_TABLE(nxAlarmView, nxView)
32 EVT_SIZE(nxAlarmView::OnSize)
33 EVT_LIST_ITEM_RIGHT_CLICK(wxID_LIST_CTRL, nxAlarmView::OnListItemRightClick)
34 EVT_LIST_COL_CLICK(wxID_LIST_CTRL, nxAlarmView::OnListColumnClick)
35 EVT_MENU(XRCID("menuAlarmAck"), nxAlarmView::OnAlarmAck)
36 EVT_MENU(XRCID("menuAlarmTerminate"), nxAlarmView::OnAlarmTerminate)
37 EVT_MENU(XRCID("menuAlarmDelete"), nxAlarmView::OnAlarmDelete)
38 END_EVENT_TABLE()
39
40
41 //
42 // Constructor
43 //
44
45 nxAlarmView::nxAlarmView(wxWindow *parent, const TCHAR *context, NXC_OBJECT *object)
46 : nxView(parent)
47 {
48 wxConfigBase *cfg = wxConfig::Get();
49 wxString path = cfg->GetPath();
50
51 m_context = context;
52 m_object = object;
53
54 cfg->SetPath(m_context);
55 cfg->Read(_T("AlarmView/SortMode"), &m_sortMode, 0);
56 cfg->Read(_T("AlarmView/SortDir"), &m_sortDir, -1);
57
58 m_wndListCtrl = new wxListView(this, wxID_LIST_CTRL, wxDefaultPosition, wxDefaultSize,
59 wxLC_REPORT | wxLC_HRULES | wxLC_VRULES);
60 m_wndListCtrl->InsertColumn(0, _T("Severity"), wxLIST_FORMAT_LEFT, 70);
61 m_wndListCtrl->InsertColumn(1, _T("State"), wxLIST_FORMAT_LEFT, 70);
62 m_wndListCtrl->InsertColumn(2, _T("Source"), wxLIST_FORMAT_LEFT, 120);
63 m_wndListCtrl->InsertColumn(3, _T("Message"), wxLIST_FORMAT_LEFT, 200);
64 m_wndListCtrl->InsertColumn(4, _T("Count"), wxLIST_FORMAT_LEFT, 40);
65 m_wndListCtrl->InsertColumn(5, _T("Created"), wxLIST_FORMAT_LEFT, 70);
66 m_wndListCtrl->InsertColumn(6, _T("Last Change"), wxLIST_FORMAT_LEFT, 70);
67 wxImageList *imgList = NXMCGetImageListCopy(IMAGE_LIST_STATUS_SMALL);
68 imgList->Add(wxXmlResource::Get()->LoadIcon(_T("icoSmallOutstanding")));
69 imgList->Add(wxXmlResource::Get()->LoadIcon(_T("icoSmallAcknowledged")));
70 imgList->Add(wxXmlResource::Get()->LoadIcon(_T("icoSmallTerminated")));
71 imgList->Add(wxXmlResource::Get()->LoadIcon(_T("icoSortUp")));
72 imgList->Add(wxXmlResource::Get()->LoadIcon(_T("icoSortDown")));
73 m_wndListCtrl->AssignImageList(imgList, wxIMAGE_LIST_SMALL);
74 NXMCLoadListCtrlColumns(cfg, *m_wndListCtrl, _T("AlarmView"));
75
76 cfg->SetPath(path);
77
78 SetIcon(wxXmlResource::Get()->LoadIcon(_T("icoAlarmView")));
79
80 NXMCEvtConnect(nxEVT_NXC_ALARM_CHANGE, wxCommandEventHandler(nxAlarmView::OnAlarmChange), this);
81 }
82
83
84 //
85 // Destructor
86 //
87
88 nxAlarmView::~nxAlarmView()
89 {
90 NXMCEvtDisconnect(nxEVT_NXC_ALARM_CHANGE, wxCommandEventHandler(nxAlarmView::OnAlarmChange), this);
91
92 wxConfigBase *cfg = wxConfig::Get();
93 wxString path = cfg->GetPath();
94 cfg->SetPath(m_context);
95 cfg->Write(_T("AlarmView/SortMode"), m_sortMode);
96 cfg->Write(_T("AlarmView/SortDir"), m_sortDir);
97 NXMCSaveListCtrlColumns(cfg, *m_wndListCtrl, _T("AlarmView"));
98 cfg->SetPath(path);
99 }
100
101
102 //
103 // Resize handler
104 //
105
106 void nxAlarmView::OnSize(wxSizeEvent &event)
107 {
108 wxSize size = GetClientSize();
109 m_wndListCtrl->SetSize(0, 0, size.x, size.y);
110 }
111
112
113 //
114 // Refresh view
115 //
116
117 void nxAlarmView::RefreshView()
118 {
119 nxAlarmList *list;
120 nxAlarmList::iterator it;
121
122 m_wndListCtrl->DeleteAllItems();
123 list = NXMCGetAlarmList();
124
125 for(it = list->begin(); it != list->end(); it++)
126 {
127 if (MatchAlarm(it->second))
128 AddAlarm(it->second);
129 }
130
131 NXMCUnlockAlarmList();
132
133 SortAlarmList();
134 }
135
136
137 //
138 // Check if alarm matched to current filter settings
139 //
140
141 bool nxAlarmView::MatchAlarm(NXC_ALARM *alarm)
142 {
143 if (m_object == NULL)
144 return true;
145 if (m_object->dwId == alarm->dwSourceObject)
146 return true;
147 return NXCIsParent(NXMCGetSession(), m_object->dwId, alarm->dwSourceObject) ? true : false;
148 }
149
150
151 //
152 // Add alarm to view
153 //
154
155 void nxAlarmView::AddAlarm(NXC_ALARM *alarm)
156 {
157 long item;
158
159 item = m_wndListCtrl->InsertItem(0x7FFFFFFF, NXMCGetStatusTextSmall(alarm->nCurrentSeverity), alarm->nCurrentSeverity);
160 if (item != -1)
161 {
162 m_wndListCtrl->SetItemData(item, alarm->dwAlarmId);
163 UpdateAlarm(item, alarm);
164 }
165 }
166
167
168 //
169 // Update alarm in view
170 //
171
172 void nxAlarmView::UpdateAlarm(long item, NXC_ALARM *alarm)
173 {
174 NXC_OBJECT *object;
175 TCHAR temp[64];
176
177 m_wndListCtrl->SetItem(item, 0, NXMCGetStatusTextSmall(alarm->nCurrentSeverity), alarm->nCurrentSeverity);
178 m_wndListCtrl->SetItem(item, 1, NXMCGetAlarmStateName(alarm->nState), alarm->nState + STATUS_TESTING + 1);
179
180 object = NXCFindObjectById(NXMCGetSession(), alarm->dwSourceObject);
181 if (object != NULL)
182 {
183 m_wndListCtrl->SetItem(item, 2, object->szName);
184 }
185 else
186 {
187 m_wndListCtrl->SetItem(item, 2, _T("<unknown>"));
188 }
189
190 m_wndListCtrl->SetItem(item, 3, alarm->szMessage);
191
192 _stprintf(temp, _T("%d"), alarm->dwRepeatCount);
193 m_wndListCtrl->SetItem(item, 4, temp);
194
195 m_wndListCtrl->SetItem(item, 5, NXMCFormatTimeStamp(alarm->dwCreationTime, temp, TS_LONG_DATE_TIME));
196 m_wndListCtrl->SetItem(item, 6, NXMCFormatTimeStamp(alarm->dwLastChangeTime, temp, TS_LONG_DATE_TIME));
197 }
198
199
200 //
201 // Handler for right click on item
202 //
203
204 void nxAlarmView::OnListItemRightClick(wxListEvent &event)
205 {
206 wxMenu *menu;
207
208 if (!IsBusy())
209 {
210 menu = wxXmlResource::Get()->LoadMenu(_T("menuCtxAlarm"));
211 if (menu != NULL)
212 {
213 PopupMenu(menu);
214 delete menu;
215 }
216 }
217 }
218
219
220 //
221 // Alarm comparision callback
222 //
223
224 static nxAlarmList *s_alarmList;
225
226 static int wxCALLBACK CompareAlarms(long item1, long item2, long sortData)
227 {
228 long mode = sortData & 0x7FFF;
229 int rc;
230 nxAlarmList::iterator it1, it2;
231 NXC_OBJECT *obj1, *obj2;
232
233 it1 = s_alarmList->find(item1);
234 it2 = s_alarmList->find(item2);
235 if ((it1 == s_alarmList->end()) || (it2 == s_alarmList->end()))
236 {
237 wxLogDebug(_T("CompareAlarms: invalid iterator returned"));
238 return 0; // Shouldn't happen
239 }
240
241 switch(mode)
242 {
243 case 0: // Severity
244 rc = COMPARE_NUMBERS(it1->second->nCurrentSeverity, it2->second->nCurrentSeverity);
245 break;
246 case 1: // State
247 rc = COMPARE_NUMBERS(it1->second->nState, it2->second->nState);
248 break;
249 case 2: // Source
250 obj1 = NXCFindObjectById(NXMCGetSession(), it1->second->dwSourceObject);
251 obj2 = NXCFindObjectById(NXMCGetSession(), it2->second->dwSourceObject);
252 rc = _tcsicmp((obj1 != NULL) ? obj1->szName : _T("(null)"), (obj2 != NULL) ? obj2->szName : _T("(null)"));
253 break;
254 case 3: // Message
255 rc = _tcsicmp(it1->second->szMessage, it2->second->szMessage);
256 break;
257 case 4: // Count
258 rc = COMPARE_NUMBERS(it1->second->dwRepeatCount, it2->second->dwRepeatCount);
259 break;
260 case 5: // Created
261 rc = COMPARE_NUMBERS(it1->second->dwCreationTime, it2->second->dwCreationTime);
262 break;
263 case 6: // Last changed
264 rc = COMPARE_NUMBERS(it1->second->dwLastChangeTime, it2->second->dwLastChangeTime);
265 break;
266 default:
267 rc = 0;
268 break;
269 }
270
271 return (sortData & 0x8000) ? rc : -rc;
272 }
273
274
275 //
276 // Sort alarm list
277 //
278
279 void nxAlarmView::SortAlarmList()
280 {
281 s_alarmList = NXMCGetAlarmList();
282 m_wndListCtrl->SortItems(CompareAlarms, m_sortMode | ((m_sortDir == 1) ? 0x8000 : 0));
283 NXMCUnlockAlarmList();
284
285 // Mark sorting column
286 m_wndListCtrl->SetColumnImage(m_sortMode, STATUS_TESTING + ((m_sortDir == 1) ? 4 : 5));
287 }
288
289
290 //
291 // Handler for column click
292 //
293
294 void nxAlarmView::OnListColumnClick(wxListEvent &event)
295 {
296 m_wndListCtrl->ClearColumnImage(m_sortMode);
297
298 if (m_sortMode == event.GetColumn())
299 {
300 m_sortDir = -m_sortDir;
301 }
302 else
303 {
304 m_sortMode = event.GetColumn();
305 }
306 SortAlarmList();
307 }
308
309
310 //
311 // Handler for alarm change event
312 //
313
314 void nxAlarmView::OnAlarmChange(wxCommandEvent &event)
315 {
316 long item;
317 NXC_ALARM *alarm;
318
319 alarm = (NXC_ALARM *)event.GetClientData();
320 switch(event.GetInt())
321 {
322 case NX_NOTIFY_NEW_ALARM:
323 case NX_NOTIFY_ALARM_CHANGED:
324 item = m_wndListCtrl->FindItem(-1, alarm->dwAlarmId);
325 if (item != -1)
326 {
327 if (MatchAlarm(alarm))
328 UpdateAlarm(item, (NXC_ALARM *)event.GetClientData());
329 else
330 m_wndListCtrl->DeleteItem(item); // Alarm no longer match filter
331 }
332 else
333 {
334 if (MatchAlarm(alarm))
335 AddAlarm(alarm);
336 }
337 SortAlarmList();
338 break;
339 case NX_NOTIFY_ALARM_TERMINATED:
340 case NX_NOTIFY_ALARM_DELETED:
341 item = m_wndListCtrl->FindItem(-1, alarm->dwAlarmId);
342 if (item != -1)
343 m_wndListCtrl->DeleteItem(item);
344 break;
345 }
346 event.Skip();
347 }
348
349
350 //
351 // Handler for acknowledge alarm menu
352 //
353
354 static DWORD AckAlarms(int count, DWORD *list)
355 {
356 int i;
357 DWORD rcc;
358 NXC_SESSION session = NXMCGetSession();
359
360 for(i = 0; i < count; i++)
361 {
362 rcc = NXCAcknowledgeAlarm(session, list[i]);
363 if (rcc != RCC_SUCCESS)
364 break;
365 }
366 delete list;
367 return rcc;
368 }
369
370 void nxAlarmView::OnAlarmAck(wxCommandEvent &event)
371 {
372 int i, count = m_wndListCtrl->GetSelectedItemCount();
373 DWORD *idList = new DWORD[count];
374 long item;
375
376 for(i = 0, item = -1; i < count; i++)
377 {
378 item = m_wndListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
379 if (item == -1)
380 break;
381 idList[i] = m_wndListCtrl->GetItemData(item);
382 }
383 DoRequestArg2((void *)AckAlarms, count, CAST_FROM_POINTER(idList, wxUIntPtr), _T("Cannot acknowledge alarm: %s"));
384 }
385
386
387 //
388 // Handler for terminate alarm menu
389 //
390
391 static DWORD TerminateAlarms(int count, DWORD *list)
392 {
393 int i;
394 DWORD rcc;
395 NXC_SESSION session = NXMCGetSession();
396
397 for(i = 0; i < count; i++)
398 {
399 rcc = NXCTerminateAlarm(session, list[i]);
400 if (rcc != RCC_SUCCESS)
401 break;
402 }
403 delete list;
404 return rcc;
405 }
406
407 void nxAlarmView::OnAlarmTerminate(wxCommandEvent &event)
408 {
409 int i, count = m_wndListCtrl->GetSelectedItemCount();
410 DWORD *idList = new DWORD[count];
411 long item;
412
413 for(i = 0, item = -1; i < count; i++)
414 {
415 item = m_wndListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
416 if (item == -1)
417 break;
418 idList[i] = m_wndListCtrl->GetItemData(item);
419 }
420 DoRequestArg2((void *)TerminateAlarms, count, CAST_FROM_POINTER(idList, wxUIntPtr), _T("Cannot terminate alarm: %s"));
421 }
422
423
424 //
425 // Handler for delete alarm menu
426 //
427
428 static DWORD DeleteAlarms(int count, DWORD *list)
429 {
430 int i;
431 DWORD rcc;
432 NXC_SESSION session = NXMCGetSession();
433
434 for(i = 0; i < count; i++)
435 {
436 rcc = NXCDeleteAlarm(session, list[i]);
437 if (rcc != RCC_SUCCESS)
438 break;
439 }
440 delete list;
441 return rcc;
442 }
443
444 void nxAlarmView::OnAlarmDelete(wxCommandEvent &event)
445 {
446 int i, count = m_wndListCtrl->GetSelectedItemCount();
447 DWORD *idList = new DWORD[count];
448 long item;
449
450 for(i = 0, item = -1; i < count; i++)
451 {
452 item = m_wndListCtrl->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
453 if (item == -1)
454 break;
455 idList[i] = m_wndListCtrl->GetItemData(item);
456 }
457 DoRequestArg2((void *)DeleteAlarms, count, CAST_FROM_POINTER(idList, wxUIntPtr), _T("Cannot delete alarm: %s"));
458 }