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