Improve error handling for Icinga Studio

refs #10042
This commit is contained in:
Gunnar Beutner 2015-09-30 09:40:29 +02:00
parent f570875c8b
commit eb2d4f2184
2 changed files with 65 additions and 17 deletions

View File

@ -22,6 +22,7 @@
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <wx/msgdlg.h>
using namespace icinga; using namespace icinga;
@ -39,7 +40,7 @@ MainForm::MainForm(wxWindow *parent, const Url::Ptr& url)
port = "5665"; port = "5665";
m_ApiClient = new ApiClient(url->GetHost(), port, url->GetUsername(), url->GetPassword()); m_ApiClient = new ApiClient(url->GetHost(), port, url->GetUsername(), url->GetPassword());
m_ApiClient->GetTypes(boost::bind(&MainForm::TypesCompletionHandler, this, _2, true)); m_ApiClient->GetTypes(boost::bind(&MainForm::TypesCompletionHandler, this, _1, _2, true));
std::string title = url->Format() + " - Icinga Studio"; std::string title = url->Format() + " - Icinga Studio";
SetTitle(title); SetTitle(title);
@ -47,14 +48,26 @@ MainForm::MainForm(wxWindow *parent, const Url::Ptr& url)
m_ObjectsList->InsertColumn(0, "Name", 0, 300); m_ObjectsList->InsertColumn(0, "Name", 0, 300);
} }
void MainForm::TypesCompletionHandler(const std::vector<ApiType::Ptr>& types, bool forward) void MainForm::TypesCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiType::Ptr>& types, bool forward)
{ {
if (forward) { if (forward) {
CallAfter(boost::bind(&MainForm::TypesCompletionHandler, this, types, false)); CallAfter(boost::bind(&MainForm::TypesCompletionHandler, this, eptr, types, false));
return; return;
} }
m_TypesTree->DeleteAllItems(); m_TypesTree->DeleteAllItems();
if (eptr) {
try {
boost::rethrow_exception(eptr);
} catch (const std::exception& ex) {
std::string message = "HTTP query failed: " + std::string(ex.what());
wxMessageBox(message, "Icinga Studio", wxOK | wxCENTRE | wxICON_ERROR, this);
Close();
return;
}
}
wxTreeItemId rootNode = m_TypesTree->AddRoot("root"); wxTreeItemId rootNode = m_TypesTree->AddRoot("root");
bool all = false; bool all = false;
@ -101,25 +114,37 @@ void MainForm::OnTypeSelected(wxTreeEvent& event)
std::vector<String> attrs; std::vector<String> attrs;
attrs.push_back(type->Name.ToLower() + ".__name"); attrs.push_back(type->Name.ToLower() + ".__name");
m_ApiClient->GetObjects(type->PluralName, boost::bind(&MainForm::ObjectsCompletionHandler, this, _2, true), m_ApiClient->GetObjects(type->PluralName, boost::bind(&MainForm::ObjectsCompletionHandler, this, _1, _2, true),
std::vector<String>(), attrs); std::vector<String>(), attrs);
} }
void MainForm::ObjectsCompletionHandler(const std::vector<ApiObject::Ptr>& objects, bool forward) void MainForm::ObjectsCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiObject::Ptr>& objects, bool forward)
{ {
if (forward) { if (forward) {
CallAfter(boost::bind(&MainForm::ObjectsCompletionHandler, this, objects, false)); CallAfter(boost::bind(&MainForm::ObjectsCompletionHandler, this, eptr, objects, false));
return; return;
} }
m_ObjectsList->DeleteAllItems();
m_PropertyGrid->Clear();
if (eptr) {
try {
boost::rethrow_exception(eptr);
} catch (const std::exception& ex) {
std::string message = "HTTP query failed: " + std::string(ex.what());
wxMessageBox(message, "Icinga Studio", wxOK | wxCENTRE | wxICON_ERROR, this);
return;
}
}
wxTreeItemId selectedId = m_TypesTree->GetSelection(); wxTreeItemId selectedId = m_TypesTree->GetSelection();
wxString typeName = m_TypesTree->GetItemText(selectedId); wxString typeName = m_TypesTree->GetItemText(selectedId);
ApiType::Ptr type = m_Types[typeName.ToStdString()]; ApiType::Ptr type = m_Types[typeName.ToStdString()];
String nameAttr = type->Name.ToLower() + ".__name"; String nameAttr = type->Name.ToLower() + ".__name";
m_ObjectsList->DeleteAllItems();
BOOST_FOREACH(const ApiObject::Ptr& object, objects) { BOOST_FOREACH(const ApiObject::Ptr& object, objects) {
std::map<String, Value>::const_iterator it = object->Attrs.find(nameAttr); std::map<String, Value>::const_iterator it = object->Attrs.find(nameAttr);
if (it == object->Attrs.end()) if (it == object->Attrs.end())
@ -150,7 +175,7 @@ void MainForm::OnObjectSelected(wxListEvent& event)
std::vector<String> names; std::vector<String> names;
names.push_back(objectName); names.push_back(objectName);
m_ApiClient->GetObjects(type->PluralName, boost::bind(&MainForm::ObjectDetailsCompletionHandler, this, _2, true), names); m_ApiClient->GetObjects(type->PluralName, boost::bind(&MainForm::ObjectDetailsCompletionHandler, this, _1, _2, true), names);
} }
wxPGProperty *MainForm::ValueToProperty(const String& name, const Value& value) wxPGProperty *MainForm::ValueToProperty(const String& name, const Value& value)
@ -190,33 +215,55 @@ wxPGProperty *MainForm::ValueToProperty(const String& name, const Value& value)
} }
} }
void MainForm::ObjectDetailsCompletionHandler(const std::vector<ApiObject::Ptr>& objects, bool forward) void MainForm::ObjectDetailsCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiObject::Ptr>& objects, bool forward)
{ {
if (forward) { if (forward) {
CallAfter(boost::bind(&MainForm::ObjectDetailsCompletionHandler, this, objects, false)); CallAfter(boost::bind(&MainForm::ObjectDetailsCompletionHandler, this, eptr, objects, false));
return; return;
} }
m_PropertyGrid->Clear();
if (eptr) {
try {
boost::rethrow_exception(eptr);
} catch (const std::exception& ex) {
std::string message = "HTTP query failed: " + std::string(ex.what());
wxMessageBox(message, "Icinga Studio", wxOK | wxCENTRE | wxICON_ERROR, this);
}
}
wxTreeItemId selectedId = m_TypesTree->GetSelection(); wxTreeItemId selectedId = m_TypesTree->GetSelection();
wxString typeName = m_TypesTree->GetItemText(selectedId); wxString typeName = m_TypesTree->GetItemText(selectedId);
ApiType::Ptr type = m_Types[typeName.ToStdString()]; ApiType::Ptr type = m_Types[typeName.ToStdString()];
String nameAttr = type->Name.ToLower() + ".__name"; String nameAttr = type->Name.ToLower() + ".__name";
m_PropertyGrid->Clear();
if (objects.empty()) if (objects.empty())
return; return;
ApiObject::Ptr object = objects[0]; ApiObject::Ptr object = objects[0];
std::map<String, wxStringProperty *> parents;
typedef std::pair<String, Value> kv_pair; typedef std::pair<String, Value> kv_pair;
BOOST_FOREACH(const kv_pair& kv, object->Attrs) { BOOST_FOREACH(const kv_pair& kv, object->Attrs) {
std::vector<String> tokens; std::vector<String> tokens;
boost::algorithm::split(tokens, kv.first, boost::is_any_of(".")); boost::algorithm::split(tokens, kv.first, boost::is_any_of("."));
std::map<String, wxStringProperty *>::const_iterator it = parents.find(tokens[0]);
wxStringProperty *parent;
if (it == parents.end()) {
parent = new wxStringProperty(tokens[0].GetData(), wxPG_LABEL, "<object>");
m_PropertyGrid->Append(parent);
parents[tokens[0]] = parent;
} else
parent = it->second;
wxPGProperty *prop = ValueToProperty(tokens[1], kv.second); wxPGProperty *prop = ValueToProperty(tokens[1], kv.second);
m_PropertyGrid->Append(prop); parent->AppendChild(prop);
m_PropertyGrid->SetPropertyReadOnly(prop); m_PropertyGrid->SetPropertyReadOnly(prop);
} }
} }

View File

@ -22,6 +22,7 @@
#include "icinga-studio/apiclient.hpp" #include "icinga-studio/apiclient.hpp"
#include "remote/url.hpp" #include "remote/url.hpp"
#include "base/exception.hpp"
#include "icinga-studio/forms.h" #include "icinga-studio/forms.h"
namespace icinga namespace icinga
@ -41,9 +42,9 @@ private:
ApiClient::Ptr m_ApiClient; ApiClient::Ptr m_ApiClient;
std::map<String, ApiType::Ptr> m_Types; std::map<String, ApiType::Ptr> m_Types;
void TypesCompletionHandler(const std::vector<ApiType::Ptr>& types, bool forward); void TypesCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiType::Ptr>& types, bool forward);
void ObjectsCompletionHandler(const std::vector<ApiObject::Ptr>& objects, bool forward); void ObjectsCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiObject::Ptr>& objects, bool forward);
void ObjectDetailsCompletionHandler(const std::vector<ApiObject::Ptr>& objects, bool forward); void ObjectDetailsCompletionHandler(boost::exception_ptr eptr, const std::vector<ApiObject::Ptr>& objects, bool forward);
wxPGProperty *ValueToProperty(const String& name, const Value& value); wxPGProperty *ValueToProperty(const String& name, const Value& value);
}; };