OSDN Git Service

Notify thread idx updated to board window.
[fukui-no-namari/fukui-no-namari.git] / src / Hage1 / board_window.py
1 # Copyright (C) 2006 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
3 #
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.
8 #
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.
13 #
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
17
18 import pygtk
19 pygtk.require('2.0')
20 import gtk
21 import gtk.glade
22 import os
23 import time
24 import gobject
25
26 import board_data
27 import thread_window
28 import misc
29 from threadlistmodel import ThreadListModel
30
31 import windowlist
32 import brdlist_window
33 import brdlist
34
35 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
36                          "..", "data")
37 GLADE_FILENAME = "board_window.glade"
38
39 def open_board(bbs, board):
40     if not bbs:
41         raise ValueError, "parameter must not be empty"
42
43     key = "/" + bbs + "/" + board
44     winwrap = windowlist.get_window(key)
45     if winwrap:
46         # already opened
47         winwrap.window.present()
48         pass
49     else:
50         win_wrap = WinWrap(bbs, board)
51         windowlist.window_created(key, win_wrap)
52
53
54 class WinWrap:
55
56     def __init__(self, bbs, board):
57         self.bbs = bbs
58         self.board = board
59
60         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
61         self.widget_tree = gtk.glade.XML(glade_path)
62
63         self.window = self.widget_tree.get_widget("board_window")
64
65         title = brdlist.get(bbs, board, "name")
66         if title:
67             self.window.set_title(title)
68
69         self.treeview = self.widget_tree.get_widget("treeview")
70         self.treeview.set_model(ThreadListModel())
71
72         self.popupmenu = self.widget_tree.get_widget("popup_menu")
73
74         renderer = gtk.CellRendererText()
75
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])
89
90         self.treeviewcolumn["lastModified"].set_cell_data_func(
91             renderer, self.on_data_lastmodified)
92
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,
101                   "on_close_activate":
102                   self.on_close_activate,
103                   "on_show_board_list_activate":
104                   self.on_show_board_list_activate,
105                   "on_popup_menu_open_activate": self.on_open_thread}
106         self.widget_tree.signal_autoconnect(sigdic)
107
108         t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
109         t.start()
110
111     def updated_thread_highlight(self, column, cell, model, iter):
112
113         def is_updated_thread():
114             res = model.get_value(
115                 iter, ThreadListModel.column_names.index("res"))
116             linecount = model.get_value(
117                 iter, ThreadListModel.column_names.index("lineCount"))
118             return res != 0 and linecount != 0 and res > linecount
119
120         if is_updated_thread():
121             cell.set_property("weight", 800)
122         else:
123             cell.set_property("weight", 400)
124
125     def on_cell_data(self, column, cell, model, iter, column_name):
126         self.updated_thread_highlight(column, cell, model, iter)
127         column_num = ThreadListModel.column_names.index(column_name)
128         value = model.get_value(iter, column_num)
129         if model.get_column_type(column_num) == gobject.TYPE_INT:
130             if value == 0:
131                 cell.set_property("text", "")
132             else:
133                 cell.set_property("text", str(value))
134         else:
135             cell.set_property("text", value)
136
137     def on_data_lastmodified(self, column, cell, model, iter, user_data=None):
138         self.updated_thread_highlight(column, cell, model, iter)
139         lastmod = model.get_value(
140             iter, ThreadListModel.column_names.index("lastModified"))
141         if lastmod == 0:
142             cell.set_property("text", "")
143         else:
144             cell.set_property("text", time.strftime(
145                 "%Y/%m/%d(%a) %H:%M:%S", time.localtime(lastmod)))
146
147     def on_board_window_destroy(self, widget):
148         pass
149
150     def on_quit_activate(self, widget):
151         gtk.main_quit()
152
153     def on_close_activate(self, widget):
154         self.window.destroy()
155
156     def on_show_board_list_activate(self, widget):
157         brdlist_window.open_brdlist(self.bbs)
158
159     def on_load_local_activate(self, widget):
160         t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
161         t.start()
162
163     def on_get_remote_activate(self, widget):
164         t = board_data.GetRemote(self.bbs, self.board, self.update_datastore)
165         t.start()
166
167     def on_column_clicked(self, treeviewcolumn, column_name):
168         model = self.treeview.get_model()
169         if model:
170             model.sort(column_name)
171             self.reset_sort_indicator()
172
173     def reset_sort_indicator(self):
174         model = self.treeview.get_model()
175         if model:
176             sort_column_name, sort_reverse = model.get_sort()
177             for name,column in self.treeviewcolumn.iteritems():
178                 column.set_sort_indicator(False)
179             if sort_column_name != "num" or sort_reverse:
180                 self.treeviewcolumn[sort_column_name].set_sort_indicator(True)
181                 if sort_reverse:
182                     self.treeviewcolumn[sort_column_name].set_sort_order(
183                         gtk.SORT_DESCENDING)
184                 else:
185                     self.treeviewcolumn[sort_column_name].set_sort_order(
186                         gtk.SORT_ASCENDING)
187         
188     def on_open_thread(self, widget):
189         treeselection = self.treeview.get_selection()
190         model, iter = treeselection.get_selected()
191         if not iter:
192             return
193
194         thread = model.get_value(iter, ThreadListModel.column_names.index("id"))
195         title = model.get_value(
196             iter, ThreadListModel.column_names.index("title"))
197         print thread + ':"' + title + '"', "activated"
198
199         thread_window.open_thread(self.bbs, self.board, thread)
200
201     def on_treeview_button_press_event(self, widget, event):
202         if event.button == 3:
203             x = int(event.x)
204             y = int(event.y)
205             time = event.time
206             pthinfo = widget.get_path_at_pos(x, y)
207             if pthinfo is not None:
208                 path, col, cellx, celly = pthinfo
209                 widget.grab_focus()
210                 widget.set_cursor(path, col, 0)
211                 self.popupmenu.popup(None, None, None, event.button, time)
212             return 1
213
214     def update_datastore(self, datalist, lastmod):
215         print "reflesh datastore"
216
217         try:
218             lastmod = misc.httpdate_to_secs(lastmod)
219         except:
220             lastmod = 0
221
222         time_start = time.time()
223         list_list = []
224         for id, dic in datalist.iteritems():
225             dic["id"] = id
226
227             # average
228             if lastmod == 0 or dic["num"] == 0:
229                 dic["average"] = 0
230             else:
231                 res = dic["res"]
232                 start = int(id)
233                 # avoid the Last-Modified time of subject.txt and
234                 # the build time of thread is equal (zero division)
235                 dur = lastmod - start
236                 if dur == 0:
237                     dic["average"] = 999999
238                 else:
239                     dic["average"] = int(res * 60 * 60 * 24 / dur)
240
241             # lastModified
242             httpdate = dic["lastModified"]
243             try:
244                 secs = misc.httpdate_to_secs(httpdate)
245                 dic["lastModified"] = secs
246             except ValueError:
247                 dic["lastModified"] = 0
248             
249             list_list.append(dic)
250
251         model = self.treeview.get_model()
252         model.set_list(list_list)
253
254         # redraw visible area after set list to model
255         self.treeview.queue_draw()
256
257         self.reset_sort_indicator()
258
259         print "end"
260         time_end = time.time()
261         print time_end - time_start
262
263     def on_thread_idx_updated(self, thread, idx_dic):
264         if not thread or not idx_dic:
265             return
266
267         model = self.treeview.get_model()
268         if model:
269             idx_dic["id"] = thread
270             try:
271                 idx_dic["lastModified"] =  misc.httpdate_to_secs(
272                     idx_dic["lastModified"])
273             except ValueError:
274                 idx_dic["lastModified"] = 0
275             model.modify_row(idx_dic)