00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <gui_utils/logview.h>
00025 #include <gui_utils/connection_dispatcher.h>
00026 #include <netcomm/fawkes/client.h>
00027 #include <netcomm/utils/network_logger.h>
00028
00029 #include <gtkmm.h>
00030
00031 namespace fawkes {
00032 #if 0
00033 }
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 LogView::LogView()
00047 {
00048 ctor();
00049 }
00050
00051
00052
00053
00054
00055
00056 LogView::LogView(const char *hostname, unsigned short int port)
00057 {
00058 ctor(hostname, port);
00059 }
00060
00061
00062 #ifdef HAVE_GLADEMM
00063
00064
00065
00066
00067
00068 LogView::LogView(BaseObjectType* cobject,
00069 const Glib::RefPtr<Gnome::Glade::Xml>& refxml)
00070 : Gtk::TreeView(cobject)
00071 {
00072 ctor();
00073 }
00074 #endif
00075
00076
00077
00078 LogView::~LogView()
00079 {
00080 FawkesNetworkClient *c = __connection_dispatcher->get_client();
00081 if (c && c->connected()) {
00082 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_NETWORKLOGGER,
00083 NetworkLogger::MSGTYPE_UNSUBSCRIBE);
00084 c->enqueue(msg);
00085 }
00086 delete __connection_dispatcher;
00087 }
00088
00089
00090
00091 void
00092 LogView::ctor(const char *hostname, unsigned short int port)
00093 {
00094 __list = Gtk::ListStore::create(__record);
00095 __have_recently_added_path = false;
00096
00097 __list->signal_row_inserted().connect(sigc::mem_fun(*this, &LogView::on_row_inserted));
00098 set_model(__list);
00099 get_selection()->set_mode(Gtk::SELECTION_NONE);
00100
00101 if ( (hostname != NULL) && (port != 0) ) {
00102 __connection_dispatcher = new ConnectionDispatcher(hostname, port, FAWKES_CID_NETWORKLOGGER);
00103 } else {
00104 __connection_dispatcher = new ConnectionDispatcher(FAWKES_CID_NETWORKLOGGER);
00105 }
00106
00107 append_column("Level", __record.loglevel);
00108 append_column("Time", __record.time);
00109 int compcol = append_column("Component", __record.component);
00110 int msgcol = append_column("Message", __record.message);
00111
00112
00113
00114 compcol -= 1;
00115 msgcol -= 1;
00116
00117 Glib::ListHandle<Gtk::TreeViewColumn *> columns = get_columns();
00118 int colnum = -1;
00119 for (Glib::ListHandle<Gtk::TreeViewColumn *>::iterator c = columns.begin(); c != columns.end(); ++c) {
00120 ++colnum;
00121 Gtk::CellRenderer *cell_renderer = (*c)->get_first_cell_renderer();
00122 Gtk::CellRendererText *text_renderer = dynamic_cast<Gtk::CellRendererText *>(cell_renderer);
00123 if ( text_renderer ) {
00124 #ifdef GLIBMM_PROPERTIES_ENABLED
00125 if ( (colnum == compcol) || (colnum == msgcol) ) {
00126 (*c)->set_resizable();
00127 }
00128 if ( colnum == compcol ) {
00129 text_renderer->property_ellipsize().set_value(Pango::ELLIPSIZE_END);
00130 }
00131
00132 (*c)->add_attribute(text_renderer->property_background_gdk(), __record.background);
00133 (*c)->add_attribute(text_renderer->property_foreground_gdk(), __record.foreground);
00134 #else
00135 (*c)->add_attribute(*text_renderer, "background-gdk", __record.background);
00136 (*c)->add_attribute(*text_renderer, "foreground-gdk", __record.background);
00137 #endif
00138 }
00139 }
00140
00141 __connection_dispatcher->signal_message_received().connect(sigc::mem_fun(*this, &LogView::on_message_received));
00142 __connection_dispatcher->signal_connected().connect(sigc::mem_fun(*this, &LogView::on_client_connected));
00143 __connection_dispatcher->signal_disconnected().connect(sigc::mem_fun(*this, &LogView::on_client_disconnected));
00144 signal_expose_event().connect_notify(sigc::mem_fun(*this, &LogView::on_expose_notify));
00145 }
00146
00147
00148
00149
00150
00151 void
00152 LogView::set_client(FawkesNetworkClient *client)
00153 {
00154 FawkesNetworkClient *c = __connection_dispatcher->get_client();
00155 if (c && c->connected()) {
00156 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_NETWORKLOGGER,
00157 NetworkLogger::MSGTYPE_UNSUBSCRIBE);
00158 c->enqueue(msg);
00159 }
00160 __connection_dispatcher->set_client(client);
00161 if (client && client->connected()) {
00162 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_NETWORKLOGGER,
00163 NetworkLogger::MSGTYPE_SUBSCRIBE);
00164 client->enqueue(msg);
00165 }
00166 }
00167
00168
00169
00170
00171
00172 FawkesNetworkClient *
00173 LogView::get_client()
00174 {
00175 return __connection_dispatcher->get_client();
00176 }
00177
00178
00179
00180
00181
00182 ConnectionDispatcher *
00183 LogView::get_connection_dispatcher() const
00184 {
00185 return __connection_dispatcher;
00186 }
00187
00188
00189
00190 void
00191 LogView::clear()
00192 {
00193 __list->clear();
00194 }
00195
00196
00197
00198
00199
00200
00201 void
00202 LogView::on_row_inserted(const Gtk::TreeModel::Path& path,
00203 const Gtk::TreeModel::iterator& iter)
00204 {
00205 Gtk::TreeModel::Path vstart, vend;
00206 Gtk::TreeModel::Path prev = path;
00207 get_visible_range(vstart, vend);
00208 prev = path;
00209 if (! get_visible_range(vstart, vend) ||
00210 ( prev.prev() &&
00211 ((vend == prev) ||
00212 (__have_recently_added_path && (__recently_added_path == prev)))) ) {
00213 scroll_to_row(path);
00214
00215
00216
00217
00218 __have_recently_added_path = true;
00219 __recently_added_path = path;
00220 }
00221 }
00222
00223
00224 void
00225 LogView::on_expose_notify(GdkEventExpose *event)
00226 {
00227 __have_recently_added_path = false;
00228 }
00229
00230 void
00231 LogView::on_client_connected()
00232 {
00233 FawkesNetworkClient *c = __connection_dispatcher->get_client();
00234 if (c && c->connected()) {
00235 FawkesNetworkMessage *msg = new FawkesNetworkMessage(FAWKES_CID_NETWORKLOGGER,
00236 NetworkLogger::MSGTYPE_SUBSCRIBE);
00237 c->enqueue(msg);
00238 struct timeval t;
00239 gettimeofday(&t, NULL);
00240 append_message(Logger::LL_DEBUG, t, "LogView", false, "Connected");
00241 }
00242 }
00243
00244 void
00245 LogView::on_client_disconnected()
00246 {
00247 struct timeval t;
00248 gettimeofday(&t, NULL);
00249 append_message(Logger::LL_ERROR, t, "LogView", false, "*** Connection died. ***");
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 void
00261 LogView::append_message(Logger::LogLevel log_level, struct timeval t,
00262 const char *component, bool is_exception,
00263 const char *message)
00264 {
00265 const char *loglevel;
00266 const char *timestr;
00267 char* time = NULL;
00268 Gdk::Color color;
00269 bool set_foreground = false;
00270 bool set_background = false;
00271
00272 switch ( log_level ) {
00273 case Logger::LL_DEBUG:
00274 loglevel = "DEBUG";
00275 color.set_rgb_p(0.4, 0.4, 0.4);
00276 set_foreground = true;
00277 break;
00278 case Logger::LL_INFO:
00279 loglevel = "INFO";
00280 break;
00281 case Logger::LL_WARN:
00282 loglevel = "WARN";
00283 color.set_rgb_p(1.0, 1.0, 0.7);
00284 set_background = true;
00285 break;
00286 case Logger::LL_ERROR:
00287 loglevel = "ERROR";
00288 color.set_rgb_p(1.0, 0.8, 0.8);
00289 set_background = true;
00290 break;
00291 default:
00292 loglevel = "NONE?";
00293 color.set_rgb_p(1.0, 0.0, 0.0);
00294 set_background = true;
00295 break;
00296 }
00297
00298 struct tm time_tm;
00299 localtime_r(&(t.tv_sec), &time_tm);
00300 if (asprintf(&time, "%02d:%02d:%02d.%06ld", time_tm.tm_hour,
00301 time_tm.tm_min, time_tm.tm_sec, t.tv_usec) == -1) {
00302 timestr = "OutOfMemory";
00303 } else {
00304 timestr = time;
00305 }
00306
00307 Gtk::TreeModel::Row row = *__list->append();
00308 row[__record.loglevel] = loglevel;
00309 row[__record.time] = timestr;
00310 row[__record.component] = component;
00311 if ( is_exception ) {
00312 row[__record.message] = std::string("[EXCEPTION] ") + message;
00313 } else {
00314 row[__record.message] = message;
00315 }
00316 if ( set_foreground ) row[__record.foreground] = color;
00317 if ( set_background ) row[__record.background] = color;
00318
00319 if (time) free(time);
00320 }
00321
00322
00323
00324
00325 void
00326 LogView::on_message_received(FawkesNetworkMessage *msg)
00327 {
00328 if ( (msg->cid() == FAWKES_CID_NETWORKLOGGER) &&
00329 (msg->msgid() == NetworkLogger::MSGTYPE_LOGMESSAGE) ) {
00330
00331 NetworkLoggerMessageContent* content = msg->msgc<NetworkLoggerMessageContent>();
00332
00333 append_message(content->get_loglevel(), content->get_time(),
00334 content->get_component(),
00335 content->is_exception(), content->get_message());
00336
00337 delete content;
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346 LogView::LogRecord::LogRecord()
00347 {
00348 add(loglevel);
00349 add(time);
00350 add(component);
00351 add(message);
00352 add(foreground);
00353 add(background);
00354 }
00355
00356
00357
00358 }