00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config_tree_view.h"
00024 #include "config_edit_dialog.h"
00025 #include "config_add_dialog.h"
00026 #include "config_remove_dialog.h"
00027 #include "config_editor_plugin.h"
00028
00029 #include <core/exceptions/system.h>
00030 #include <config/netconf.h>
00031 #include <config/sqlite.h>
00032 #include <netcomm/fawkes/client.h>
00033
00034 #include <cstring>
00035 #include <iostream>
00036 #include <sstream>
00037
00038 using namespace std;
00039 using namespace fawkes;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 ConfigTreeView::ConfigTreeView( BaseObjectType* cobject,
00094 const Glib::RefPtr<Gnome::Glade::Xml>& ref_xml)
00095 : Gtk::TreeView(cobject)
00096 {
00097 m_dlg_edit = NULL;
00098 ref_xml->get_widget_derived("dlgConfigEdit", m_dlg_edit);
00099
00100 m_dlg_add = NULL;
00101 ref_xml->get_widget_derived("dlgConfigAdd", m_dlg_add);
00102
00103 m_dlg_remove = NULL;
00104 ref_xml->get_widget_derived("dlgConfigRemove", m_dlg_remove);
00105
00106 m_config_tree = Gtk::TreeStore::create(m_config_record);
00107 m_config_tree->set_sort_column(0, Gtk::SORT_ASCENDING);
00108
00109 set_model(m_config_tree);
00110 append_column("Path", m_config_record.node);
00111
00112 Gtk::TreeViewColumn *column = get_column(0);
00113 Gtk::CellRendererText *cell = (Gtk::CellRendererText *)column->get_first_cell_renderer();
00114 #ifdef GLIBMM_PROPERTIES_ENABLED
00115 column->add_attribute(cell->property_underline(), m_config_record.is_default);
00116 #else
00117 column->add_attribute(*cell, "underline", m_config_record.is_default);
00118 #endif
00119
00120 append_column("Value", m_config_record.value_string);
00121
00122 Gtk::Menu::MenuList& menulist = m_menu.items();
00123
00124 menulist.push_back( Gtk::Menu_Helpers::MenuElem("Edit", sigc::mem_fun( *this, &ConfigTreeView::on_menu_edit_selected) ) );
00125 menulist.push_back( Gtk::Menu_Helpers::MenuElem("Remove", sigc::mem_fun( *this, &ConfigTreeView::on_menu_remove_selected) ) );
00126 menulist.push_back( Gtk::Menu_Helpers::MenuElem("Add", sigc::mem_fun( *this, &ConfigTreeView::on_menu_add_selected) ) );
00127
00128 m_config = NULL;
00129 m_own_config = false;
00130
00131 signal_button_press_event().connect_notify( sigc::mem_fun(*this, &ConfigTreeView::on_button_press_event_custom) );
00132 }
00133
00134
00135 ConfigTreeView::~ConfigTreeView()
00136 {
00137 if (m_own_config)
00138 { delete m_config; }
00139
00140 for ( std::map< string, ConfigEditorPlugin* >::iterator iter = m_plugins.begin();
00141 iter != m_plugins.end();
00142 ++iter )
00143 { delete iter->second; }
00144 }
00145
00146
00147
00148
00149
00150 void
00151 ConfigTreeView::set_config(Configuration* config)
00152 {
00153 if ( config )
00154 {
00155 m_config = config;
00156 m_own_config = false;
00157
00158
00159 read_config();
00160 }
00161 else
00162 {
00163 delete m_config;
00164 m_config = NULL;
00165 m_config_tree->clear();
00166 }
00167
00168 for ( std::map< string, ConfigEditorPlugin* >::iterator i = m_plugins.begin();
00169 i != m_plugins.end();
00170 ++i )
00171 { i->second->set_config( m_config ); }
00172 }
00173
00174
00175
00176
00177
00178 void
00179 ConfigTreeView::set_network_client(FawkesNetworkClient* client)
00180 {
00181 if (client)
00182 {
00183 NetworkConfiguration* netconf = new NetworkConfiguration(client);
00184 netconf->set_mirror_mode(true);
00185 m_config = netconf;
00186 m_own_config = true;
00187
00188 read_config();
00189 }
00190 else
00191 {
00192 delete m_config;
00193 m_config = NULL;
00194 m_config_tree->clear();
00195 }
00196
00197 for ( std::map< string, ConfigEditorPlugin* >::iterator i = m_plugins.begin();
00198 i != m_plugins.end();
00199 ++i )
00200 { i->second->set_config( m_config ); }
00201 }
00202
00203
00204
00205
00206 void
00207 ConfigTreeView::set_config_file(const char* filename)
00208 {
00209 m_config = new SQLiteConfiguration(filename);
00210 m_own_config = true;
00211
00212 read_config();
00213 }
00214
00215
00216
00217
00218
00219 void
00220 ConfigTreeView::register_plugin( ConfigEditorPlugin* plugin )
00221 {
00222 plugin->initialize();
00223 m_plugins[ plugin->get_config_path() ] = plugin;
00224 }
00225
00226
00227
00228
00229
00230 void
00231 ConfigTreeView::remove_plugin( string config_path )
00232 {
00233 std::map< string, ConfigEditorPlugin* >::iterator iter = m_plugins.find( config_path );
00234
00235 if ( iter != m_plugins.end() )
00236 {
00237 ConfigEditorPlugin* p = iter->second;
00238 m_plugins.erase( iter );
00239 delete p;
00240 }
00241 }
00242
00243 void
00244 ConfigTreeView::read_config()
00245 {
00246 if ( !m_config )
00247 { return; }
00248
00249 m_config_tree->clear();
00250
00251 m_config->lock();
00252 Configuration::ValueIterator* cit = m_config->iterator();
00253 while ( cit->next() )
00254 {
00255 if ( cit->is_bool() )
00256 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_bool()); }
00257 else if ( cit->is_int() )
00258 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_int()); }
00259 else if ( cit->is_uint() )
00260 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_uint()); }
00261 else if ( cit->is_float() )
00262 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_float()); }
00263 else if ( cit->is_string() )
00264 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_string()); }
00265 }
00266
00267 delete cit;
00268 m_config->unlock();
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278 void
00279 ConfigTreeView::set_value(const char* path, const char* type, bool is_default, bool value)
00280 {
00281 Gtk::TreeModel::Row row;
00282 row = *get_iter(path);
00283
00284 row[m_config_record.type] = type;
00285 row[m_config_record.is_default] = is_default;
00286 row[m_config_record.value_bool] = value;
00287 row[m_config_record.value_string] = ( value ? "TRUE" : "FALSE" );
00288 }
00289
00290
00291
00292
00293
00294
00295
00296 void
00297 ConfigTreeView::set_value(const char* path, const char* type, bool is_default, int value)
00298 {
00299 Gtk::TreeModel::Row row;
00300 row = *get_iter(path);
00301
00302 row[m_config_record.type] = type;
00303 row[m_config_record.is_default] = is_default;
00304 row[m_config_record.value_int] = value;
00305
00306 string val_str;
00307 stringstream ss;
00308 ss << value;
00309 ss >> val_str;
00310 row[m_config_record.value_string] = val_str;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319 void
00320 ConfigTreeView::set_value(const char* path, const char* type, bool is_default, uint value)
00321 {
00322 Gtk::TreeModel::Row row;
00323 row = *get_iter(path);
00324
00325 row[m_config_record.type] = type;
00326 row[m_config_record.is_default] = is_default;
00327 row[m_config_record.value_uint] = value;
00328
00329 string val_str;
00330 stringstream ss;
00331 ss << value;
00332 ss >> val_str;
00333 row[m_config_record.value_string] = val_str;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 void
00343 ConfigTreeView::set_value(const char* path, const char* type, bool is_default, float value)
00344 {
00345 Gtk::TreeModel::Row row;
00346 row = *get_iter(path);
00347
00348 row[m_config_record.type] = type;
00349 row[m_config_record.is_default] = is_default;
00350 row[m_config_record.value_float] = value;
00351
00352 string val_str;
00353 stringstream ss;
00354 ss << value;
00355 ss >> val_str;
00356 row[m_config_record.value_string] = val_str;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365 void
00366 ConfigTreeView::set_value(const char* path, const char* type, bool is_default, std::string value)
00367 {
00368 Gtk::TreeModel::Row row;
00369 row = *get_iter(path);
00370
00371 row[m_config_record.type] = type;
00372 row[m_config_record.is_default] = is_default;
00373 row[m_config_record.value_string] = value;
00374 }
00375
00376 Gtk::TreeIter
00377 ConfigTreeView::get_iter(const char* p)
00378 {
00379 char* path;
00380 char* full_path;
00381
00382 if (asprintf(&full_path, "%s", p) == -1) {
00383 throw OutOfMemoryException("get_iter(): asprintf() failed");
00384 }
00385 char* node = strtok(full_path, "/");
00386
00387 if (asprintf(&path, "/%s", node) == -1) {
00388 throw OutOfMemoryException("get_iter(): asprintf() failed");
00389 }
00390
00391 Gtk::TreeModel::Children children = m_config_tree->children();
00392 Gtk::TreeIter iter = children.begin();
00393
00394 while ( node != NULL )
00395 {
00396 bool found = false;
00397 iter = children.begin();
00398
00399 while ( !found && iter != children.end() )
00400 {
00401 Gtk::TreeModel::Row row = *iter;
00402
00403 Glib::ustring r = row[m_config_record.node];
00404 if ( strcmp(r.c_str(), node) == 0 )
00405 {
00406 found = true;
00407 children = row.children();
00408 iter = children.begin();
00409 }
00410 else
00411 { ++iter; }
00412 }
00413
00414 if ( !found )
00415 {
00416 iter = m_config_tree->append(children);
00417 Gtk::TreeModel::Row row = *iter;
00418 row[m_config_record.node] = Glib::ustring(node);
00419 row[m_config_record.path] = Glib::ustring(path);
00420
00421 children = row.children();
00422 }
00423
00424 node = strtok(NULL, "/");
00425
00426 char* t;
00427 if (asprintf(&t, "%s/%s", path, node) == -1) {
00428 throw OutOfMemoryException("get_iter(): asprintf() failed");
00429 }
00430 free(path);
00431 path = t;
00432 }
00433
00434 free(path);
00435 free(full_path);
00436
00437 return iter;
00438 }
00439
00440 Gtk::TreeIter
00441 ConfigTreeView::search_path( const char* path )
00442 {
00443 Gtk::TreeModel::Children children = m_config_tree->children();
00444 Gtk::TreeModel::iterator iter = children.begin();
00445
00446 while ( iter != children.end() )
00447 {
00448 Gtk::TreeModel::Row row = *iter;
00449 Glib::ustring p = row[ m_config_record.path ];
00450 size_t len = strlen( p.c_str() );
00451
00452 if ( strncmp( p.c_str(), path, len) == 0 )
00453 {
00454 if ( strcmp( p.c_str(), path ) == 0 )
00455 { return iter; }
00456 else
00457 { iter = iter->children().begin(); }
00458 }
00459 else
00460 { ++iter; }
00461 }
00462
00463 return m_config_tree->children().end();
00464 }
00465
00466
00467
00468
00469
00470 void
00471 ConfigTreeView::on_button_press_event_custom(GdkEventButton* event)
00472 {
00473 if (event->type == GDK_2BUTTON_PRESS)
00474 {
00475 Gtk::TreeModel::Row row = *( get_selection()->get_selected() );
00476 Glib::ustring path = row[ m_config_record.path ];
00477
00478 std::map< string, ConfigEditorPlugin* >::iterator i = m_plugins.find( path.c_str() );
00479 if ( i != m_plugins.end() )
00480 { i->second->run(); }
00481 else
00482 { edit_entry( get_selection()->get_selected() ); }
00483 }
00484 else if ( event->type == GDK_BUTTON_PRESS && (event->button == 3) )
00485 {
00486 m_menu.popup(event->button, event->time);
00487 }
00488 }
00489
00490
00491
00492
00493 void ConfigTreeView::on_menu_edit_selected()
00494 {
00495 edit_entry( get_selection()->get_selected() );
00496 }
00497
00498
00499
00500
00501 void
00502 ConfigTreeView::on_menu_add_selected()
00503 {
00504 add_entry( get_selection()->get_selected() );
00505 }
00506
00507
00508
00509
00510 void
00511 ConfigTreeView::on_menu_remove_selected()
00512 {
00513 remove_entry( get_selection()->get_selected() );
00514 }
00515
00516 bool
00517 ConfigTreeView::edit_entry(const Gtk::TreeIter& iter)
00518 {
00519 bool ret_val;
00520
00521 Gtk::TreeModel::Row row = *iter;
00522 Glib::ustring type = row[m_config_record.type];
00523
00524 if (type == "")
00525 { ret_val = false; }
00526 else
00527 {
00528 int result;
00529 Glib::ustring path = row[m_config_record.path];
00530 Glib::ustring value = row[m_config_record.value_string];
00531 bool is_default = row[m_config_record.is_default];
00532
00533 m_dlg_edit->init(path, type, value);
00534 Gtk::Window* parent = dynamic_cast<Gtk::Window*>( get_toplevel() );
00535 m_dlg_edit->set_transient_for(*parent);
00536 result = m_dlg_edit->run();
00537
00538 switch (result)
00539 {
00540 case Gtk::RESPONSE_OK:
00541 {
00542 Glib::ustring value = m_dlg_edit->get_value();
00543
00544 const char* p = path.c_str();
00545 const char* t = type.c_str();
00546
00547 is_default = m_dlg_edit->get_is_default();
00548 if (is_default) m_config->erase(p);
00549
00550 if ( m_config->is_bool(p) )
00551 {
00552 bool b = false;
00553 if (value == "TRUE")
00554 { b = true; }
00555 else if (value == "FALSE")
00556 { b = false; }
00557
00558 if (!is_default) m_config->set_bool(p, b);
00559 else m_config->set_default_bool(p, b);
00560 set_value(p, t, is_default, b);
00561 }
00562 else if ( m_config->is_int(p) )
00563 {
00564 int i;
00565 i = atoi( value.c_str() );
00566
00567 if (!is_default) m_config->set_int(p, i);
00568 else m_config->set_default_int(p, i);
00569 set_value(p, t, is_default, i);
00570 }
00571 else if ( m_config->is_uint(p) )
00572 {
00573 int i;
00574 i = atoi( value.c_str() );
00575 if ( 0 <= i)
00576 {
00577 if (!is_default) m_config->set_uint(p, (unsigned int) i);
00578 else m_config->set_default_uint( p, (unsigned int) i );
00579 set_value(p, t, is_default, (unsigned int) i);
00580 }
00581 }
00582 else if ( m_config->is_float(p) )
00583 {
00584 float f;
00585 f = atof( value.c_str() );
00586
00587 if (!is_default) m_config->set_float(p, f);
00588 else m_config->set_default_float(p, f);
00589 set_value(p, t, is_default, f);
00590 }
00591 else if ( m_config->is_string(p) )
00592 {
00593 string s( value.c_str() );
00594
00595 if (!is_default) m_config->set_string(p, s);
00596 else m_config->set_default_string(p, s);
00597 set_value(p, t, is_default, s);
00598 }
00599
00600 ret_val = true;
00601
00602 break;
00603 }
00604
00605 default:
00606 ret_val = false;
00607 break;
00608 }
00609
00610 m_dlg_edit->hide();
00611 }
00612
00613 return ret_val;
00614 }
00615
00616 bool
00617 ConfigTreeView::remove_entry(const Gtk::TreeIter& iter)
00618 {
00619 bool ret_val = false;
00620 int result;
00621 Gtk::TreeModel::Row row = *iter;
00622 Glib::ustring type = row[m_config_record.type];
00623 bool is_default = row[m_config_record.is_default];
00624
00625 if (type == "")
00626 { ret_val = false; }
00627 else
00628 {
00629 Glib::ustring path = row[m_config_record.path];
00630 m_dlg_remove->init(path, is_default);
00631
00632 Gtk::Window* parent = dynamic_cast<Gtk::Window*>( get_toplevel() );
00633 m_dlg_remove->set_transient_for(*parent);
00634 result = m_dlg_remove->run();
00635
00636 switch (result)
00637 {
00638 case Gtk::RESPONSE_OK:
00639 {
00640 const char* p = path.c_str();
00641 bool rem_default = m_dlg_remove->get_remove_default();
00642 m_config->erase(p);
00643 if (rem_default) m_config->erase_default(p);
00644
00645 Gtk::TreePath tree_path = m_config_tree->get_path(iter);
00646 m_config_tree->erase(iter);
00647 m_config_tree->row_deleted(tree_path);
00648
00649 Configuration::ValueIterator* cit = m_config->search(p);
00650 if (!rem_default && cit->next())
00651 {
00652 if ( cit->is_bool() )
00653 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_bool()); }
00654 else if ( cit->is_int() )
00655 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_int()); }
00656 else if ( cit->is_uint() )
00657 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_uint()); }
00658 else if ( cit->is_float() )
00659 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_float()); }
00660 else if ( cit->is_string() )
00661 { set_value(cit->path(), cit->type(), cit->is_default(), cit->get_string()); }
00662 }
00663
00664 break;
00665 }
00666
00667 default:
00668 ret_val = false;
00669 break;
00670 }
00671
00672 m_dlg_remove->hide();
00673 }
00674
00675 return ret_val;
00676 }
00677
00678 bool
00679 ConfigTreeView::add_entry(const Gtk::TreeIter& iter)
00680 {
00681 bool ret_val = false;
00682 int result;
00683 Gtk::TreeModel::Row row = *iter;
00684 Glib::ustring path = row[m_config_record.path];
00685
00686 m_dlg_add->init(path);
00687
00688 Gtk::Window* parent = dynamic_cast<Gtk::Window*>( get_toplevel() );
00689 m_dlg_add->set_transient_for(*parent);
00690 result = m_dlg_add->run();
00691
00692 switch (result)
00693 {
00694 case Gtk::RESPONSE_OK:
00695 {
00696 Glib::ustring type = m_dlg_add->get_type();
00697 Glib::ustring path = m_dlg_add->get_path();
00698 Glib::ustring value = m_dlg_add->get_value();
00699 bool is_default = m_dlg_add->get_is_default();
00700
00701 const char* t = type.c_str();
00702 const char* p = path.c_str();
00703
00704 ret_val = true;
00705
00706 if ( type == "bool" )
00707 {
00708 bool b = false;
00709
00710 if ( value == "TRUE" || value == "true" )
00711 { b = true; }
00712 else if ( value == "FALSE" || value == "false" )
00713 { b = false; }
00714
00715 if (!is_default) m_config->set_bool(p, b);
00716 else m_config->set_default_bool(p, b);
00717 set_value(p, t, is_default, b);
00718 }
00719
00720 else if ( type == "int" )
00721 {
00722 int i;
00723 i = atoi( value.c_str() );
00724
00725 if (!is_default) m_config->set_int(p, i);
00726 else m_config->set_default_int(p, i);
00727 set_value(p, t, is_default, i);
00728 }
00729
00730 else if ( type == "uint" )
00731 {
00732 int i;
00733 i = atoi( value.c_str() );
00734 if ( 0 <= i)
00735 {
00736 if (!is_default) m_config->set_uint(p, (unsigned int) i);
00737 else m_config->set_default_uint( p, (unsigned int) i);
00738 set_value(p, t, is_default, (unsigned int) i);
00739 }
00740 }
00741
00742 else if ( type == "float" )
00743 {
00744 float f;
00745 f = atof( value.c_str() );
00746
00747 if (!is_default) m_config->set_float(p, f);
00748 else m_config->set_default_float(p, f);
00749 set_value(p, t, is_default, f);
00750 }
00751
00752 else if ( type == "string")
00753 {
00754 string s( value.c_str() );
00755
00756 if (!is_default) m_config->set_string(p, s);
00757 else m_config->set_default_string(p, s);
00758 set_value(p, t, is_default, s);
00759 }
00760
00761 else
00762 {
00763 ret_val = false;
00764 cout << "Unknown type." << endl;
00765 }
00766
00767 break;
00768 }
00769
00770 default:
00771 ret_val = false;
00772 break;
00773 }
00774
00775 m_dlg_add->hide();
00776
00777 return ret_val;
00778 }