1 # Copyright (C) 2006 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
32 GLADE_FILENAME = "board_window.glade"
37 def __init__(self, bbs, board):
41 glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
42 self.mainwin = gtk.glade.XML(glade_path)
44 self.treeview = self.mainwin.get_widget("treeview")
45 self.treeview.set_rules_hint(True)
47 self.popupmenu = self.mainwin.get_widget("popup_menu")
49 renderer = gtk.CellRendererText()
51 self.treeviewcolumn = {}
52 for i in range(1, len(ThreadListModel.column_names)):
53 column_name = ThreadListModel.column_names[i]
54 self.treeviewcolumn[column_name] = gtk.TreeViewColumn(
55 column_name, renderer)
56 self.treeviewcolumn[column_name].set_resizable(True)
57 self.treeviewcolumn[column_name].set_reorderable(True)
58 self.treeviewcolumn[column_name].set_clickable(True)
59 self.treeviewcolumn[column_name].set_cell_data_func(
60 renderer, self.on_cell_data, column_name)
61 self.treeviewcolumn[column_name].connect(
62 "clicked", self.on_column_clicked, column_name)
63 self.treeview.append_column(self.treeviewcolumn[column_name])
65 self.treeviewcolumn["lastModified"].set_cell_data_func(
66 renderer, self.on_data_lastmodified)
68 sigdic = {"on_board_window_destroy": self.on_board_window_destroy,
69 "on_quit_activate": self.on_quit_activate,
70 "on_load_local_activate": self.on_load_local_activate,
71 "on_get_remote_activate": self.on_get_remote_activate,
72 "on_treeview_row_activated":
73 lambda w,p,v: self.on_open_thread(w),
74 "on_treeview_button_press_event":
75 self.on_treeview_button_press_event,
76 "on_popup_menu_open_activate": self.on_open_thread}
77 self.mainwin.signal_autoconnect(sigdic)
79 def updated_thread_highlight(self, column, cell, model, iter):
81 def is_updated_thread():
82 res = model.get_value(
83 iter, ThreadListModel.column_names.index("res"))
84 linecount = model.get_value(
85 iter, ThreadListModel.column_names.index("lineCount"))
86 return res != 0 and linecount != 0 and res > linecount
88 if is_updated_thread():
89 cell.set_property("weight", 800)
91 cell.set_property("weight", 400)
93 def on_cell_data(self, column, cell, model, iter, column_name):
94 self.updated_thread_highlight(column, cell, model, iter)
95 column_num = ThreadListModel.column_names.index(column_name)
96 value = model.get_value(iter, column_num)
97 if model.get_column_type(column_num) == gobject.TYPE_INT:
99 cell.set_property("text", "")
101 cell.set_property("text", str(value))
103 cell.set_property("text", value)
105 def on_data_lastmodified(self, column, cell, model, iter, user_data=None):
106 self.updated_thread_highlight(column, cell, model, iter)
107 lastmod = model.get_value(
108 iter, ThreadListModel.column_names.index("lastModified"))
110 cell.set_property("text", "")
112 cell.set_property("text", time.strftime(
113 "%Y/%m/%d(%a) %H:%M:%S", time.localtime(lastmod)))
115 def on_board_window_destroy(self, widget):
118 def on_quit_activate(self, widget):
121 def on_load_local_activate(self, widget):
122 t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
125 def on_get_remote_activate(self, widget):
126 t = board_data.GetRemote(self.bbs, self.board, self.update_datastore)
129 def on_column_clicked(self, treeviewcolumn, column_name):
130 model = self.treeview.get_model()
132 model.sort(column_name)
133 self.reset_sort_indicator()
135 def reset_sort_indicator(self):
136 model = self.treeview.get_model()
138 sort_column_name, sort_reverse = model.get_sort()
139 for name,column in self.treeviewcolumn.iteritems():
140 column.set_sort_indicator(False)
141 if sort_column_name != "num" or sort_reverse:
142 self.treeviewcolumn[sort_column_name].set_sort_indicator(True)
144 self.treeviewcolumn[sort_column_name].set_sort_order(
147 self.treeviewcolumn[sort_column_name].set_sort_order(
150 def on_open_thread(self, widget):
151 treeselection = self.treeview.get_selection()
152 model, iter = treeselection.get_selected()
156 thread = model.get_value(iter, ThreadListModel.column_names.index("id"))
157 title = model.get_value(
158 iter, ThreadListModel.column_names.index("title"))
159 print thread + ':"' + title + '"', "activated"
161 thread_window.WinWrap(self.bbs, self.board, thread)
163 def on_treeview_button_press_event(self, widget, event):
164 if event.button == 3:
168 pthinfo = widget.get_path_at_pos(x, y)
169 if pthinfo is not None:
170 path, col, cellx, celly = pthinfo
172 widget.set_cursor(path, col, 0)
173 self.popupmenu.popup(None, None, None, event.button, time)
176 def update_datastore(self, datalist, lastmod):
177 print "reflesh datastore"
180 lastmod = misc.httpdate_to_secs(lastmod)
184 time_start = time.time()
186 for id, dic in datalist.iteritems():
190 if lastmod == 0 or dic["num"] == 0:
195 dic["average"] = int(res * 60 * 60 * 24 / (lastmod - start))
198 httpdate = dic["lastModified"]
200 secs = misc.httpdate_to_secs(httpdate)
201 dic["lastModified"] = secs
203 dic["lastModified"] = 0
205 list_list.append(dic)
207 model = self.treeview.get_model()
209 sort_column_name, sort_reverse = model.get_sort()
210 model = ThreadListModel(list_list, sort_column_name, sort_reverse)
212 model = ThreadListModel(list_list)
213 self.treeview.set_model(model)
215 self.reset_sort_indicator()
218 time_end = time.time()
219 print time_end - time_start
222 class ThreadListModel(gtk.GenericTreeModel):
223 column_types = (str, int, str, int, int, int, int)
224 column_names = ["id", "num", "title", "res", "lineCount",
225 "lastModified", "average"]
227 def __init__(self, list, sort_column_name="num", sort_reverse=False):
228 gtk.GenericTreeModel.__init__(self)
230 self.sort_column_name = sort_column_name
231 self.sort_reverse = sort_reverse
232 self.do_sort(self.sort_column_name, self.sort_reverse)
234 def build_order_dict(self):
235 # key: thread id, value: index in self.list
236 self.order_dict = dict(
237 [(item["id"], index) for index, item in enumerate(self.list)])
239 def compare(self, v1, v2, reverse):
241 if v1 == 0 and v2 == 0:
250 return self.sort_column_name, self.sort_reverse
252 def do_sort(self, column_name, reverse):
253 if self.column_types[self.column_names.index(column_name)] == str:
254 self.list.sort(None, lambda dic: dic[column_name], reverse)
256 h = lambda x, y: self.compare(x, y, reverse)
257 self.list.sort(h, lambda dic: dic[column_name], reverse)
258 self.build_order_dict()
260 def sort(self, column_name):
261 old_order_dict = self.order_dict
263 if column_name == self.sort_column_name:
265 self.sort_reverse = not self.sort_reverse
267 self.sort_column_name = column_name
268 self.sort_reverse = False
270 self.do_sort(self.sort_column_name, self.sort_reverse)
272 neworder = [old_order_dict[item["id"]] for item in self.list]
273 self.rows_reordered(None, None, neworder)
275 def on_get_flags(self):
276 return gtk.TREE_MODEL_LIST_ONLY
278 def on_get_n_columns(self):
279 return len(self.column_types)
281 def on_get_column_type(self, n):
282 return self.column_types[n]
284 def on_get_iter(self, path):
285 return self.list[path[0]]
287 def on_get_path(self, rowref):
288 return self.order_dict[rowref["id"]]
290 def on_get_value(self, rowref, column):
291 return rowref[self.column_names[column]]
293 def on_iter_next(self, rowref):
295 i = self.order_dict[rowref["id"]] + 1
300 def on_iter_children(self, rowref):
305 def on_iter_has_child(self, rowref):
308 def on_iter_n_children(self, rowref):
311 return len(self.list)
313 def on_iter_nth_child(self, rowref, n):
321 def on_iter_parent(self, child):