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
29 from threadlistmodel import ThreadListModel
30 from BbsType import bbs_type_judge_uri
34 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
36 GLADE_FILENAME = "board_window.glade"
40 raise ValueError, "parameter must not be empty"
42 winwrap = windowlist.get_window(uri)
45 winwrap.window.present()
48 win_wrap = WinWrap(uri)
49 windowlist.window_created(uri, win_wrap)
54 def __init__(self, uri):
56 self.bbs_type = bbs_type_judge_uri.get_type(uri)
57 self.bbs = self.bbs_type.bbs_type
58 self.host = self.bbs_type.host
59 self.board = self.bbs_type.board
60 self.uri = self.bbs_type.uri
62 glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
63 self.widget_tree = gtk.glade.XML(glade_path)
65 self.window = self.widget_tree.get_widget("board_window")
67 self.window.set_title(self.uri)
69 self.treeview = self.widget_tree.get_widget("treeview")
70 self.treeview.set_model(ThreadListModel())
72 self.popupmenu = self.widget_tree.get_widget("popup_menu")
74 renderer = gtk.CellRendererText()
76 self.treeviewcolumn = {}
77 for i in range(1, len(ThreadListModel.column_names)):
78 column_name = ThreadListModel.column_names[i]
79 self.treeviewcolumn[column_name] = gtk.TreeViewColumn(
80 column_name, renderer)
81 self.treeviewcolumn[column_name].set_resizable(True)
82 self.treeviewcolumn[column_name].set_reorderable(True)
83 self.treeviewcolumn[column_name].set_clickable(True)
84 self.treeviewcolumn[column_name].set_cell_data_func(
85 renderer, self.on_cell_data, column_name)
86 self.treeviewcolumn[column_name].connect(
87 "clicked", self.on_column_clicked, column_name)
88 self.treeview.append_column(self.treeviewcolumn[column_name])
90 self.treeviewcolumn["lastModified"].set_cell_data_func(
91 renderer, self.on_data_lastmodified)
93 sigdic = {"on_board_window_destroy": self.on_board_window_destroy,
94 "on_quit_activate": self.on_quit_activate,
95 "on_load_local_activate": self.on_load_local_activate,
96 "on_get_remote_activate": self.on_get_remote_activate,
97 "on_treeview_row_activated":
98 lambda w,p,v: self.on_open_thread(w),
99 "on_treeview_button_press_event":
100 self.on_treeview_button_press_event,
102 self.on_close_activate,
103 "on_popup_menu_open_activate": self.on_open_thread}
104 self.widget_tree.signal_autoconnect(sigdic)
106 t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
109 def updated_thread_highlight(self, column, cell, model, iter):
111 def is_updated_thread():
112 res = model.get_value(
113 iter, ThreadListModel.column_names.index("res"))
114 linecount = model.get_value(
115 iter, ThreadListModel.column_names.index("lineCount"))
116 return res != 0 and linecount != 0 and res > linecount
118 if is_updated_thread():
119 cell.set_property("weight", 800)
121 cell.set_property("weight", 400)
123 def on_cell_data(self, column, cell, model, iter, column_name):
124 self.updated_thread_highlight(column, cell, model, iter)
125 column_num = ThreadListModel.column_names.index(column_name)
126 value = model.get_value(iter, column_num)
127 if model.get_column_type(column_num) == gobject.TYPE_INT:
129 cell.set_property("text", "")
131 cell.set_property("text", str(value))
133 cell.set_property("text", value)
135 def on_data_lastmodified(self, column, cell, model, iter, user_data=None):
136 self.updated_thread_highlight(column, cell, model, iter)
137 lastmod = model.get_value(
138 iter, ThreadListModel.column_names.index("lastModified"))
140 cell.set_property("text", "")
142 cell.set_property("text", time.strftime(
143 "%Y/%m/%d(%a) %H:%M:%S", time.localtime(lastmod)))
145 def on_board_window_destroy(self, widget):
148 def on_quit_activate(self, widget):
151 def on_close_activate(self, widget):
152 self.window.destroy()
154 def on_load_local_activate(self, widget):
155 t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
158 def on_get_remote_activate(self, widget):
159 t = board_data.GetRemote(
160 self.bbs, self.board, self.bbs_type.get_subject_txt_uri(),
161 self.update_datastore)
164 def on_column_clicked(self, treeviewcolumn, column_name):
165 model = self.treeview.get_model()
167 model.sort(column_name)
168 self.reset_sort_indicator()
170 def reset_sort_indicator(self):
171 model = self.treeview.get_model()
173 sort_column_name, sort_reverse = model.get_sort()
174 for name,column in self.treeviewcolumn.iteritems():
175 column.set_sort_indicator(False)
176 if sort_column_name != "num" or sort_reverse:
177 self.treeviewcolumn[sort_column_name].set_sort_indicator(True)
179 self.treeviewcolumn[sort_column_name].set_sort_order(
182 self.treeviewcolumn[sort_column_name].set_sort_order(
185 def on_open_thread(self, widget):
186 treeselection = self.treeview.get_selection()
187 model, iter = treeselection.get_selected()
191 thread = model.get_value(iter, ThreadListModel.column_names.index("id"))
192 title = model.get_value(
193 iter, ThreadListModel.column_names.index("title"))
194 print thread + ':"' + title + '"', "activated"
196 bbs_type_for_thread = self.bbs_type.clone_with_thread(thread)
197 thread_window.open_thread(bbs_type_for_thread.get_thread_uri())
199 def on_treeview_button_press_event(self, widget, event):
200 if event.button == 3:
204 pthinfo = widget.get_path_at_pos(x, y)
205 if pthinfo is not None:
206 path, col, cellx, celly = pthinfo
208 widget.set_cursor(path, col, 0)
209 self.popupmenu.popup(None, None, None, event.button, time)
212 def update_datastore(self, datalist, lastmod):
213 print "reflesh datastore"
216 lastmod = misc.httpdate_to_secs(lastmod)
220 time_start = time.time()
222 for id, dic in datalist.iteritems():
226 if lastmod == 0 or dic["num"] == 0:
231 # avoid the Last-Modified time of subject.txt and
232 # the build time of thread is equal (zero division)
233 dur = lastmod - start
235 dic["average"] = 999999
237 dic["average"] = int(res * 60 * 60 * 24 / dur)
240 httpdate = dic["lastModified"]
242 secs = misc.httpdate_to_secs(httpdate)
243 dic["lastModified"] = secs
245 dic["lastModified"] = 0
247 list_list.append(dic)
249 model = self.treeview.get_model()
250 model.set_list(list_list)
252 # redraw visible area after set list to model
253 self.treeview.queue_draw()
255 self.reset_sort_indicator()
258 time_end = time.time()
259 print time_end - time_start
261 def on_thread_idx_updated(self, thread_uri, idx_dic):
262 if not thread_uri or not idx_dic:
265 # nothing to do if thread_uri does not belong to this board.
266 bbs_type = bbs_type_judge_uri.get_type(thread_uri)
267 if bbs_type.bbs_type != self.bbs \
268 or bbs_type.board != self.board or not bbs_type.is_thread():
271 thread = bbs_type.thread
273 model = self.treeview.get_model()
275 idx_dic["id"] = thread
277 idx_dic["lastModified"] = misc.httpdate_to_secs(
278 idx_dic["lastModified"])
280 idx_dic["lastModified"] = 0
281 model.modify_row(idx_dic)