OSDN Git Service

board window performance improvement
[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
25 import board_data
26 import thread_window
27
28 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
29                          "..", "data")
30 GLADE_FILENAME = "board_window.glade"
31
32
33 class WinWrap:
34
35     def __init__(self, bbs, board):
36         self.bbs = bbs
37         self.board = board
38
39         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
40         self.mainwin = gtk.glade.XML(glade_path)
41
42         self.treeview = self.mainwin.get_widget("treeview")
43         self.treeview.set_rules_hint(True)
44
45         self.popupmenu = self.mainwin.get_widget("popup_menu")
46
47         renderer = gtk.CellRendererText()
48
49         self.treeviewcolumn = {}
50         for i in range(1, len(ThreadListModel.column_names)):
51             column_name = ThreadListModel.column_names[i]
52             self.treeviewcolumn[column_name] = gtk.TreeViewColumn(
53                 column_name, renderer, text=i)
54             self.treeviewcolumn[column_name].set_resizable(True)
55             self.treeviewcolumn[column_name].set_reorderable(True)
56             self.treeviewcolumn[column_name].set_clickable(True)
57             self.treeviewcolumn[column_name].connect(
58                 "clicked", self.on_column_clicked, column_name)
59             self.treeview.append_column(self.treeviewcolumn[column_name])
60
61         sigdic = {"on_board_window_destroy": self.on_board_window_destroy,
62                   "on_quit_activate": self.on_quit_activate,
63                   "on_load_local_activate": self.on_load_local_activate,
64                   "on_get_remote_activate": self.on_get_remote_activate,
65                   "on_treeview_row_activated":
66                   lambda w,p,v: self.on_open_thread(w),
67                   "on_treeview_button_press_event":
68                   self.on_treeview_button_press_event,
69                   "on_popup_menu_open_activate": self.on_open_thread}
70         self.mainwin.signal_autoconnect(sigdic)
71
72     def on_board_window_destroy(self, widget):
73         gtk.main_quit()
74
75     def on_quit_activate(self, widget):
76         gtk.main_quit()
77
78     def on_load_local_activate(self, widget):
79         t = board_data.LoadLocal(self.bbs, self.board, self.update_datastore)
80         t.start()
81
82     def on_get_remote_activate(self, widget):
83         t = board_data.GetRemote(self.bbs, self.board, self.update_datastore)
84         t.start()
85
86     def on_column_clicked(self, treeviewcolumn, column_name):
87         model = self.treeview.get_model()
88         if model:
89             model.sort(column_name)
90             self.reset_sort_indicator()
91
92     def reset_sort_indicator(self):
93         model = self.treeview.get_model()
94         if model:
95             sort_column_name, sort_reverse = model.get_sort()
96             for name,column in self.treeviewcolumn.iteritems():
97                 column.set_sort_indicator(False)
98             if sort_column_name != "num" or sort_reverse:
99                 self.treeviewcolumn[sort_column_name].set_sort_indicator(True)
100                 if sort_reverse:
101                     self.treeviewcolumn[sort_column_name].set_sort_order(
102                         gtk.SORT_DESCENDING)
103                 else:
104                     self.treeviewcolumn[sort_column_name].set_sort_order(
105                         gtk.SORT_ASCENDING)
106         
107     def on_open_thread(self, widget):
108         treeselection = self.treeview.get_selection()
109         model, iter = treeselection.get_selected()
110         if not iter:
111             return
112
113         thread = model.get_value(iter, ThreadListModel.column_names.index("id"))
114         title = model.get_value(
115             iter, ThreadListModel.column_names.index("title"))
116         print thread + ':"' + title + '"', "activated"
117
118         thread_window.WinWrap(self.bbs, self.board, thread)
119
120     def on_treeview_button_press_event(self, widget, event):
121         if event.button == 3:
122             x = int(event.x)
123             y = int(event.y)
124             time = event.time
125             pthinfo = widget.get_path_at_pos(x, y)
126             if pthinfo is not None:
127                 path, col, cellx, celly = pthinfo
128                 widget.grab_focus()
129                 widget.set_cursor(path, col, 0)
130                 self.popupmenu.popup(None, None, None, event.button, time)
131             return 1
132
133     def update_datastore(self, datalist):
134         print "reflesh datastore"
135
136         time_start = time.time()
137         list_list = []
138         for id, dic in datalist.iteritems():
139             dic["id"] = id
140             list_list.append(dic)
141
142         model = self.treeview.get_model()
143         if model:
144             sort_column_name, sort_reverse = model.get_sort()
145             model = ThreadListModel(list_list, sort_column_name, sort_reverse)
146         else:
147             model = ThreadListModel(list_list)
148         self.treeview.set_model(model)
149
150         self.reset_sort_indicator()
151
152         print "end"
153         time_end = time.time()
154         print time_end - time_start
155
156
157 class ThreadListModel(gtk.GenericTreeModel):
158     column_types = (str, int, str, int, int, str)
159     column_names = ["id", "num", "title", "res", "lineCount", "lastModified"]
160
161     def __init__(self, list, sort_column_name="num", sort_reverse=False):
162         gtk.GenericTreeModel.__init__(self)
163         self.list = list
164         self.sort_column_name = sort_column_name
165         self.sort_reverse = sort_reverse
166         self.do_sort(self.sort_column_name, self.sort_reverse)
167
168     def build_order_dict(self):
169         # key: thread id, value: index in self.list
170         self.order_dict = dict(
171             [(item["id"], index) for index, item in enumerate(self.list)])
172  
173     def compare(self, v1, v2, reverse):
174         if not reverse:
175             if v1 == 0 and v2 == 0:
176                 return 0
177             elif v1 == 0:
178                 return 1
179             elif v2 == 0:
180                 return -1
181         return v1 - v2
182
183     def get_sort(self):
184         return self.sort_column_name, self.sort_reverse
185
186     def do_sort(self, column_name, reverse):
187         if self.column_types[self.column_names.index(column_name)] == str:
188             self.list.sort(None, lambda dic: dic[column_name], reverse)
189         else:
190             h = lambda x, y: self.compare(x, y, reverse)
191             self.list.sort(h, lambda dic: dic[column_name], reverse)
192         self.build_order_dict()
193
194     def sort(self, column_name):
195         old_order_dict = self.order_dict
196
197         if column_name == self.sort_column_name:
198             # sort reverse
199             self.sort_reverse = not self.sort_reverse
200         else:
201             self.sort_column_name = column_name
202             self.sort_reverse = False
203
204         self.do_sort(self.sort_column_name, self.sort_reverse)
205
206         neworder = [old_order_dict[item["id"]] for item in self.list]
207         self.rows_reordered(None, None, neworder)
208
209     def on_get_flags(self):
210         return gtk.TREE_MODEL_LIST_ONLY
211
212     def on_get_n_columns(self):
213         return len(self.column_types)
214
215     def on_get_column_type(self, n):
216         return self.column_types[n]
217
218     def on_get_iter(self, path):
219         return self.list[path[0]]
220
221     def on_get_path(self, rowref):
222         return self.order_dict[rowref["id"]]
223
224     def on_get_value(self, rowref, column):
225         return rowref[self.column_names[column]]
226
227     def on_iter_next(self, rowref):
228         try:
229             i = self.order_dict[rowref["id"]] + 1
230             return self.list[i]
231         except IndexError:
232             return None
233
234     def on_iter_children(self, rowref):
235         if rowref:
236             return None
237         return self.list[0]
238
239     def on_iter_has_child(self, rowref):
240         return False
241
242     def on_iter_n_children(self, rowref):
243         if rowref:
244             return 0
245         return len(self.list)
246
247     def on_iter_nth_child(self, rowref, n):
248         if rowref:
249             return None
250         try:
251             return self.list[n]
252         except IndexError:
253             return None
254
255     def on_iter_parent(child):
256         return None