source: projects/synaptic/trunk/gtk/rglogview.cc @ 280

Revision 280, 9.5 KB checked in by yasumichi, 15 years ago (diff)

first import

Line 
1/* rglogview.cc
2 *
3 * Copyright (c) 2004 Michael Vogt <mvo@debian.org>
4 *
5 * Author: Michael Vogt <mvo@debian.org>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 */
22
23#include <cassert>
24#include <map>
25#include "config.h"
26#include "rglogview.h"
27#include "rgmisc.h"
28
29#include "i18n.h"
30
31enum { COLUMN_LOG_DAY, 
32       COLUMN_LOG_FILENAME, 
33       N_LOG_COLUMNS };
34
35void RGLogView::readLogs()
36{
37   map<int, GtkTreeIter> history_map;
38   int history_key;
39
40   GtkTreeStore *store = gtk_tree_store_new(N_LOG_COLUMNS, 
41                                            G_TYPE_STRING,
42                                            G_TYPE_STRING);
43   
44   GtkTreeIter month_iter;  /* Parent iter */
45   GtkTreeIter date_iter;  /* Child iter  */
46
47   unsigned int year, month, day, hour, min, sec;
48   char str[128];
49   const gchar *logfile;
50   const gchar *logdir = RLogDir().c_str();
51   GDir *dir = g_dir_open(logdir, 0, NULL);
52   while((logfile=g_dir_read_name(dir)) != NULL) {
53      if(sscanf(logfile, "%4u-%2u-%2u.%2u%2u%2u.log", 
54                &year, &month, &day, &hour, &min, &sec) != 6)
55         continue;
56
57      struct tm t;
58      t.tm_year = year-1900;
59      t.tm_mon = month-1;
60      t.tm_mday = day;
61      t.tm_hour = hour;
62      t.tm_min = min;
63      t.tm_sec = sec;
64      GDate *date = g_date_new_dmy(day, (GDateMonth)month, year);
65      // need to convert here:
66      // glib: 1=Monday to 7=Sunday
67      // libc: 0=Sunday to 6=Saturday
68      t.tm_wday = g_date_get_weekday(date); 
69      t.tm_wday %= 7;
70
71      history_key = year*100+month;
72      if(history_map.count(history_key) == 0) {
73         gtk_tree_store_append(store, &month_iter, NULL); 
74         strftime(str, 128, "%B %Y", &t);
75         gchar *sort_key = g_strdup_printf("%i", history_key);
76         gtk_tree_store_set (store, &month_iter,
77                             COLUMN_LOG_DAY, utf8(str),
78                             COLUMN_LOG_FILENAME, sort_key, 
79                             -1);
80         g_free(sort_key);
81         history_map.insert(make_pair<int,GtkTreeIter>(history_key,month_iter));
82      } else {
83         month_iter = history_map[history_key];
84      }
85
86      strftime(str, 512, "%x %R", &t);
87      gtk_tree_store_append (store, &date_iter, &month_iter);
88      gtk_tree_store_set (store, &date_iter,
89                          COLUMN_LOG_DAY, utf8(str),
90                          COLUMN_LOG_FILENAME, logfile, 
91                          -1);
92      g_free(date);
93   }
94   g_dir_close(dir);
95
96   GtkTreeModel *sort_model;
97   /* Create the first tree */
98   sort_model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(store));
99
100   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model),
101                                         COLUMN_LOG_FILENAME, 
102                                         GTK_SORT_DESCENDING);
103   gtk_tree_view_set_model(GTK_TREE_VIEW(_treeView), 
104                           GTK_TREE_MODEL(sort_model));
105   _realModel = sort_model;
106}
107
108void RGLogView::cbCloseClicked(GtkWidget *self, void *data)
109{
110   RGLogView *me = (RGLogView*)data;
111   me->close();
112}
113
114void RGLogView::cbTreeSelectionChanged(GtkTreeSelection *selection, 
115                                      gpointer data)
116{
117   //cout << "cbTreeSelectionChanged()" << endl;
118   RGLogView *me = (RGLogView*)data;
119   
120   GtkTreeIter iter;
121   GtkTreeModel *model;
122   GtkTextIter start, end;
123   gchar *file = NULL;
124
125   if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
126         GtkTextBuffer *buffer;
127         GtkTextIter start,end;
128
129         gtk_tree_model_get (model, &iter, COLUMN_LOG_FILENAME, &file, -1);
130         // the months do not have a valid file
131         if(!FileExists(RLogDir()+string(file)))
132            return;
133
134         buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(me->_textView));
135         gtk_text_buffer_get_start_iter (buffer, &start);
136         gtk_text_buffer_get_end_iter(buffer,&end);
137         gtk_text_buffer_delete(buffer,&start,&end);
138   
139         string logfile = RLogDir() + string(file);
140         ifstream in(logfile.c_str());
141         string s;
142         while(getline(in, s)) {
143            // no need to free str later, it is allocated in a static buffer
144            const char *str = utf8(s.c_str());
145            if(str!=NULL) {
146               gtk_text_buffer_get_end_iter(buffer, &end);
147               int line = gtk_text_iter_get_line(&end);
148               gtk_text_buffer_insert_at_cursor(buffer, str, -1);
149               if(me->findStr) {
150                  char *off = g_strstr_len(str, strlen(str), me->findStr);
151                  if(off) {
152                     gtk_text_buffer_get_iter_at_line_index(buffer, &start, 
153                                                            line, off-str);
154                     gtk_text_buffer_get_iter_at_line_index(buffer, &end, 
155                                                            line, off-str+strlen(me->findStr));
156                     gtk_text_buffer_apply_tag (buffer, me->_markTag, 
157                                                &start, &end);
158                  }
159               } 
160
161            }
162            gtk_text_buffer_insert_at_cursor(buffer, "\n", -1);
163         }
164         g_free(file);
165   }
166}
167
168gboolean RGLogView::filter_func(GtkTreeModel *model, GtkTreeIter *iter,
169                                gpointer data)
170{
171   RGLogView *me = (RGLogView*)data;
172   gchar *file;
173   string s;
174
175   gtk_tree_model_get(model, iter, COLUMN_LOG_FILENAME, &file, -1);
176   // top-level expander
177   if(file == NULL) {
178      return TRUE;
179   }
180
181   string logfile = RLogDir() + string(file);
182   ifstream in(logfile.c_str());
183   if(!in) {
184      g_warning("can't open logfile: %s",logfile.c_str());
185      return FALSE;
186   }
187   while(getline(in, s)) {
188      if(s.find(me->findStr) != string::npos) {
189         return TRUE;
190      }
191   }
192
193   return FALSE;
194}
195
196gboolean empty_row_filter_func(GtkTreeModel *model, GtkTreeIter *iter, 
197                               gpointer data)
198{
199   gchar *file;
200
201   gtk_tree_model_get(model, iter, COLUMN_LOG_FILENAME, &file, -1);
202   // top-level expander
203   if(file == NULL) {
204      return gtk_tree_model_iter_has_child(model, iter);
205   }
206
207   return TRUE;
208}
209
210void RGLogView::clearLogBuf()
211{
212   GtkTextBuffer *buffer;
213   GtkTextIter start,end;
214
215   buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_textView));
216   gtk_text_buffer_get_start_iter (buffer, &start);
217   gtk_text_buffer_get_end_iter(buffer,&end);
218   gtk_text_buffer_delete(buffer,&start,&end);
219
220}
221
222void RGLogView::appendLogBuf(string text)
223{
224   GtkTextBuffer *buffer;
225   buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_textView));
226   gtk_text_buffer_insert_at_cursor(buffer, text.c_str(), -1);
227}
228
229void RGLogView::cbButtonFind(GtkWidget *self, void *data)
230{
231   //cout << "RGLogView::cbButtonFind()" << endl;
232   RGLogView *me = (RGLogView*)data;
233   GtkTreeModel *filter_model, *empty_row_filter;
234   GtkTreeIter iter; 
235   gchar *file;
236
237   GtkTreeModel *model = me->_realModel;
238   if(model == NULL) {
239      g_warning("model==NULL in cbButtonFind");
240      return;
241   }
242
243   me->clearLogBuf();
244
245   me->findStr = gtk_entry_get_text(GTK_ENTRY(me->_entryFind));
246   // reset to old model
247   if(strlen(me->findStr) == 0) {
248      me->findStr = NULL;
249      gtk_tree_view_set_model(GTK_TREE_VIEW(me->_treeView), me->_realModel);
250      return;
251   } 
252     
253   // filter for the search string
254   filter_model=(GtkTreeModel*)gtk_tree_model_filter_new(model, NULL);
255   gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter_model), 
256                                          me->filter_func, me, NULL);
257
258   // filter out empty nodes
259   empty_row_filter=(GtkTreeModel*)gtk_tree_model_filter_new(filter_model, NULL);
260   gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(empty_row_filter), 
261                                          empty_row_filter_func, me, NULL);
262   gtk_tree_view_set_model(GTK_TREE_VIEW(me->_treeView), empty_row_filter);
263
264
265   int toplevel_children = gtk_tree_model_iter_n_children(empty_row_filter, NULL);
266   if(toplevel_children == 0) {
267      me->appendLogBuf(_("Not found"));
268   } else {
269      me->appendLogBuf(_("Expression was found, please see the list "
270                         "on the left for matching entries."));
271   }
272
273   // expand to show what we found
274   gtk_tree_view_expand_all(GTK_TREE_VIEW(me->_treeView));
275}
276
277void RGLogView::show()
278{
279   clearLogBuf();
280   gtk_entry_set_text(GTK_ENTRY(_entryFind), "");
281   RGWindow::show();
282}
283
284RGLogView::RGLogView(RGWindow *parent)
285   : RGGladeWindow(parent, "logview"), findStr(NULL)
286{
287   GtkWidget *vbox = glade_xml_get_widget(_gladeXML, "vbox_main");
288   assert(vbox);
289
290   _entryFind = glade_xml_get_widget(_gladeXML, "entry_find");
291   assert(_entryFind);
292
293   _treeView = glade_xml_get_widget(_gladeXML, "treeview_dates");
294   assert(_treeView);
295   
296   GtkCellRenderer *renderer;
297   GtkTreeViewColumn *column;
298
299   renderer = gtk_cell_renderer_text_new ();
300   column = gtk_tree_view_column_new_with_attributes ("Date",
301                                                      renderer,
302                                                      "markup", COLUMN_LOG_DAY,
303                                                      NULL);
304   gtk_tree_view_append_column (GTK_TREE_VIEW(_treeView), column);
305
306   // find button
307   glade_xml_signal_connect_data(_gladeXML, "on_button_find_clicked",
308                                 G_CALLBACK(cbButtonFind), this);
309   // close
310   glade_xml_signal_connect_data(_gladeXML,"on_button_close_clicked",
311                                 G_CALLBACK(cbCloseClicked), this);
312
313 
314   /* Setup the selection handler */
315   GtkTreeSelection *select;
316   select = gtk_tree_view_get_selection(GTK_TREE_VIEW(_treeView));
317   gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
318   g_signal_connect(G_OBJECT(select), "changed",
319                    G_CALLBACK (cbTreeSelectionChanged),
320                    this);
321   _textView = glade_xml_get_widget(_gladeXML, "textview_log");
322   assert(_textView);
323
324   glade_xml_signal_connect_data(_gladeXML, "on_entry_find_activate",
325                                 G_CALLBACK(cbButtonFind), this);
326
327   GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_textView));
328   _markTag = gtk_text_buffer_create_tag (buf, "mark",
329                                          "background", "yellow", NULL); 
330
331}
Note: See TracBrowser for help on using the repository browser.