OSDN Git Service

Fix the signal of thread index update to board.
[fukui-no-namari/fukui-no-namari.git] / src / Hage1 / thread_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.path
23 import codecs
24 import re
25 import pango
26 import urllib2
27
28 import misc
29 import datfile
30 import barehtmlparser
31 import idxfile
32 import windowlist
33 import board_window
34
35 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
36                          "..", "data")
37 GLADE_FILENAME = "thread_window.glade"
38
39 def open_thread(uri):
40     if not uri:
41         raise ValueError, "parameter must not be empty"
42
43     winwrap = windowlist.get_window(uri)
44     if winwrap:
45         # already opened
46         winwrap.window.present()
47         pass
48     else:
49         win_wrap = WinWrap(uri)
50         windowlist.window_created(uri, win_wrap)
51
52
53 class WinWrap:
54
55     def __init__(self, uri):
56         from BbsType import bbs_type_judge_uri
57         from BbsType import bbs_type_exception
58         self.bbs_type = bbs_type_judge_uri.get_type(uri)
59         if not self.bbs_type.is_thread():
60             raise bbs_type_exception.BbsTypeError, \
61                   "the uri does not represent thread: " + uri
62         self.bbs = self.bbs_type.bbs_type
63         self.board = self.bbs_type.board
64         self.thread = self.bbs_type.thread
65         self.host = self.bbs_type.host
66         self.uri = self.bbs_type.uri
67         self.size = 0
68         self.num = 0
69         self.title = None
70
71         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
72         self.widget_tree = gtk.glade.XML(glade_path)
73         self.window = self.widget_tree.get_widget("thread_window")
74         self.textview = self.widget_tree.get_widget("textview")
75         self.textbuffer = self.textview.get_buffer()
76         self.enditer = self.textbuffer.get_end_iter()
77         self.boldtag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD)
78         self.leftmargintag = self.textbuffer.create_tag()
79         self.leftmargintag.set_property("left-margin", 20)
80
81         sigdic = {"on_toolbutton_refresh_clicked": self.update,
82                   "on_refresh_activate": self.update,
83                   "on_close_activate": self.on_close_activate,
84                   "on_quit_activate": self.on_quit_activate,
85                   "on_show_board_activate": self.on_show_board_activate,
86                   "on_thread_window_destroy": self.on_thread_window_destroy}
87         self.widget_tree.signal_autoconnect(sigdic)
88
89         self.load_dat()
90
91     def on_close_activate(self, widget):
92         self.window.destroy()
93
94     def on_thread_window_destroy(self, widget):
95         -1
96
97     def on_quit_activate(self, widget):
98         gtk.main_quit()
99
100     def on_show_board_activate(self, widget):
101         board_window.open_board(self.bbs_type.get_uri_base())
102
103     def http_get_dat(self, on_get_res):
104         datfile_url = self.bbs_type.get_dat_uri()
105
106         idx_dic = idxfile.load_idx(self.bbs, self.board, self.thread)
107         lastmod = idx_dic["lastModified"]
108         etag = idx_dic["etag"]
109
110         req = urllib2.Request(datfile_url)
111         if self.size > 0:
112             req.add_header("Range", "bytes=" + str(self.size) + "-")
113         if lastmod:
114             req.add_header("If-Modified-Since", lastmod)
115         if etag:
116             req.add_header("If-None-Match", etag)
117         print req.headers
118
119         res = urllib2.urlopen(req)
120         headers = res.info()
121         print headers
122
123         line = res.readline()
124         maybe_incomplete = False
125         while line:
126             if not line.endswith("\n"):
127                 maybe_incomplete = True
128                 print "does not end with \\n. maybe incomplete"
129                 break
130             on_get_res(line)
131             line = res.readline()
132
133         res.close()
134
135         if maybe_incomplete:
136             lastmod = None
137             etag = None
138         else:
139             if "Last-Modified" in headers:
140                 lastmod = headers["Last-Modified"]
141             if "ETag" in headers:
142                 etag = headers["Etag"]
143
144         if self.num > 0:
145             if not self.title:
146                 self.title = datfile.get_title_from_dat(
147                     self.bbs, self.board, self.thread)
148                 if self.title:
149                     self.window.set_title(self.title)
150             # save idx
151             idx_dic = {"title": self.title, "lineCount": self.num,
152                    "lastModified": lastmod, "etag": etag}
153             idxfile.save_idx(self.bbs, self.board, self.thread, idx_dic)
154
155             windowlist.thread_idx_updated(
156                 self.bbs_type.get_thread_uri(), idx_dic)
157
158     def update(self, widget=None):
159         line_count = datfile.get_dat_line_count(
160             self.bbs, self.board, self.thread)
161
162         if line_count > self.num:
163             datfile.load_dat_partly(
164                 self.bbs, self.board, self.thread,
165                 self.append_rawres_to_buffer, self.num+1)
166
167         dat_path = misc.get_thread_dat_path(self.bbs, self.board, self.thread)
168         dat_file = file(dat_path, "a+")
169
170         def save_line_and_append_to_buffer(line):
171             dat_file.seek(self.size)
172             dat_file.write(line)
173             self.append_rawres_to_buffer(line)
174
175         self.http_get_dat(save_line_and_append_to_buffer)
176         dat_file.close()
177
178     def load_dat(self):
179         self.size = 0
180         self.num = 0
181
182         self.title = datfile.get_title_from_dat(
183             self.bbs, self.board, self.thread)
184         if self.title:
185             self.window.set_title(self.title)
186
187         datfile.load_dat(self.bbs, self.board, self.thread,
188                          self.append_rawres_to_buffer)
189         self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0)
190
191
192     def append_rawres_to_buffer(self, line):
193         self.size += len(line)
194         self.num += 1
195
196         h = lambda name,mail,date,msg: self.reselems_to_buffer(
197             self.num, name, mail, date, msg)
198
199         datfile.split_line_to_elems(line.decode("cp932", "replace"), h)
200         
201     def reselems_to_buffer(self, num, name, mail, date, msg):
202         # number
203         self.textbuffer.insert(self.enditer, str(num) + " ")
204
205         # name
206         p = barehtmlparser.BareHTMLParser(self.untiedata_to_buffer)
207         p.feed("<b>" + name + "</b>")
208         p.close()
209
210         # mail
211         self.textbuffer.insert(self.enditer, "[" + mail + "]")
212
213         # date
214         p.feed(date)
215         p.close()
216         self.textbuffer.insert(self.enditer, "\n")
217
218         # msg
219         p.reset_func(self.untiedata_to_buffer_with_leftmargin)
220         p.feed(msg)
221         p.close()
222
223         self.textbuffer.insert(self.enditer, "\n\n")
224
225     def untiedata_to_buffer(self, data, bold, href):
226         if bold:
227             self.textbuffer.insert_with_tags(self.enditer, data, self.boldtag)
228         else:
229             self.textbuffer.insert(self.enditer, data)
230
231     def untiedata_to_buffer_with_leftmargin(self, data, bold, href):
232         if bold:
233             self.textbuffer.insert_with_tags(self.enditer, data,
234                                              self.boldtag, self.leftmargintag)
235         else:
236             self.textbuffer.insert_with_tags(self.enditer, data,
237                                              self.leftmargintag)